swwmgz_m/zscript/player/swwm_player.zsc

847 lines
25 KiB
Text

// The Demolitionist
Enum EDemoFaceState
{
FS_DEFAULT,
FS_EVIL,
FS_GRIN,
FS_WINK,
FS_BLINK,
FS_SAD,
FS_PAIN,
FS_OUCH,
FS_DEAD // UNUSED
};
Class Demolitionist : PlayerPawn
{
int last_jump_held, last_boost, last_kick;
Vector3 dashdir;
double dashfuel, dashboost;
int dashcooldown, boostcooldown, fuelcooldown;
int dashlockst;
bool fullfuel;
bool sendtoground;
bool bInDefaultInventory;
bool oldsinglefirst;
transient int lastdamage;
transient int lastdamagetic, lastdamagetimer;
bool lastground;
int lastgroundtic, lastairtic;
double lastvelz, prevvelz, landvelz;
double ssup;
SWWMStats mystats;
int cairtime;
bool hasteleported;
bool hasrevived;
int lastmpain;
double guideangle, guidepitch, guideroll;
// for weapon bobbing and stuff
double bumpvelz, bumpangle, bumppitch, bumproll;
Vector3 oldangles;
Vector3 oldlagangles, lagangles;
Vector3 oldlagdangles, lagdangles;
Vector3 oldlagvel, lagvel;
double oldlagready, lagready;
enum EUnderType
{
UNDER_NONE,
UNDER_WATER,
UNDER_SLIME,
UNDER_LAVA
};
int lastunder;
Color undercol;
int deadtimer;
transient int revivefail;
transient int bumptic;
transient double lastbump;
DemolitionistSelfLight selflight;
Actor oldencroached;
Vector3 oldencroachedpos;
int encroachtics;
Vector3 pretelepos;
SWWMItemSense itemsense;
int healcooldown, healtimer, oldhealth;
bool scriptedinvul;
bool hitactivate;
Actor froggy;
transient int lastuse, failcounter, failcooldown, mirrorcooldown;
transient SWWMItemTracer itrace;
transient SWWMMirrorTracer mtrace;
bool meleeuse;
transient bool bWalking;
int airscreamtime;
enum EInvWipe
{
WIPE_EPISODE = 1,
WIPE_CLUSTER = 2,
WIPE_MAP = 4
}
int invwipe; // inventory wipe flags for next level
transient int lastbang, lastbust, lastkiss;
transient bool ingivecheat;
Property DashFuel : dashfuel;
EDemoFaceState facestate;
int paindir;
int facetimer;
int blinktime;
transient int oldfaceidx;
transient int rss;
transient bool facedamage, facegrin, facesad, facewink, faceblink;
int oldtagcolor;
transient int magtime;
SWWMMagItem magitem;
int magitem_cnt;
SWWMShadow myshadow;
double bobtime, oldbobtime, oldbob;
bool isAnalogMoving;
// bloody footprints (yes, separate for each foot)
double footblood[2];
Color footbloodcol[2];
SWWMHandler hnd;
Default
{
Tag "$T_DEMOLITIONIST";
Speed 1;
Radius 16; // should be 9 in theory, but it'd be too thin
Height 56;
Mass 500;
PainChance 255;
MaxSlopeSteepness 0; // mountain goat mode, all slopes are walkable
Player.DisplayName "$T_DEMOLITIONIST";
// StartItem array is defined but not used directly
// just declared here for mod compat
Player.StartItem "ExplodiumGun";
Player.StartItem "DeepImpact";
Player.StartItem "AlmasteelPlating";
Player.StartItem "SayaCollar";
Player.ViewHeight 52;
Player.AirCapacity 0;
Player.GruntSpeed 20;
Player.ForwardMove 1., 1.;
Player.SideMove 1., 1.;
Player.SoundClass "demolitionist";
Player.FlyBob 0.;
Player.WaterClimbSpeed 0.;
DamageFactor "Drowning", 0.;
DamageFactor "Poison", 0.;
DamageFactor "PoisonCloud", 0.;
DamageFactor "Falling", 0.;
Demolitionist.DashFuel 240.;
+NOBLOOD;
+DONTGIB;
+NOICEDEATH;
+NOSKIN;
+DONTMORPH;
+DONTDRAIN;
+DONTCORPSE;
-WINDTHRUST; // too heavy
}
override String GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
{
if ( inflictor && inflictor.FindInventory("ParriedBuff") ) return StringTable.Localize("$O_PARRY");
if ( mod == 'Jump' ) return StringTable.Localize("$O_JUMP");
if ( mod == 'Dash' ) return StringTable.Localize("$O_DASH");
if ( mod == 'Buttslam' ) return StringTable.Localize("$O_BUTT");
if ( mod == 'GroundPound' ) return StringTable.Localize("$O_POUND");
return Super.GetObituary(victim,inflictor,mod,playerattack);
}
override double GetDeathHeight()
{
double basedeathheight = Super.GetDeathHeight();
// limit death height to crouch height, to avoid dying players from getting stuck on revive
return max(Height*.3,basedeathheight);
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
lastground = true; // prevent sudden landing sound on map start
blinktime = 30;
// prevent jumpy weapon bob on game start
oldangles = (angle,pitch,roll);
// swap ourselves for a voodoo doll
if ( !player || (player.mo != self) )
{
let v = Spawn("SWWMVoodooDoll",pos);
v.angle = angle;
v.player = player;
// give it a face if it belongs to a player
if ( player )
{
v.bFRIENDLY = true;
v.A_ChangeModel("",0,"","",1,"models","VoodooDollFace.png",CMDL_USESURFACESKIN,-1);
}
Destroy();
return;
}
oldsinglefirst = swwm_singlefirst; // super already sets up the slots, so save the cvar value now
mystats = SWWMStats.Find(player);
// sanity checks
if ( !EventHandler.Find("SWWMHandler") || !StaticEventHandler.Find("SWWMStaticHandler") )
ThrowAbortException("Panic! SWWM event handlers not detected!");
}
void BumpView( double str, Vector3 dir = (0,0,0) )
{
double dirlen = dir.length();
if ( dirlen < double.epsilon )
{
bumppitch += str;
return;
}
dir /= dirlen;
Vector3 x, y;
Quat r = Quat.FromAngles(angle+viewangle,pitch+viewpitch,roll+viewroll);
x = r*(1,0,0);
y = r*(0,-1,0);
double sx = dir dot x;
double sy = dir dot y;
if ( !sx && !sy ) bumppitch += str;
else
{
bumppitch += str*sx;
bumproll += str*sy;
}
}
override void CheckFOV()
{
if ( !player ) return;
float desired = player.desiredfov;
// adjust fov from weapon (abs due to special use of negative
// to prevent it from scaling look sensitivity)
if ( (player.playerstate != PST_DEAD) && player.readyweapon
&& player.readyweapon.fovscale )
desired *= abs(player.readyweapon.fovscale);
// additional fov bump from various effects
// akin to the old A_ZoomFactor trick, but not limited to weapons and can stack
if ( lastbump <= 0. ) lastbump = 1.;
if ( lastbump != 1. )
{
double str = CVar.GetCVar('swwm_bumpstrength',player).GetFloat();
player.fov *= lastbump*str+1.-str;
lastbump = 1.;
}
// adjust fov from dashing
double spd = vel.length();
if ( InStateSequence(CurState,FindState("Dash")) && (spd > 10.) )
{
Vector3 facedir = SWWMUtility.Vec3FromAngles(angle,pitch);
if ( spd > 0. )
{
double rel = max(0,vel.unit() dot facedir);
desired *= 1.+clamp(rel*(spd-10.),-80.,80.)*.002;
}
}
if ( player.fov == desired ) return;
// interpolate towards desired fov
if ( abs(player.fov-desired) < .1 ) player.fov = desired;
else
{
float zoom = max(.1,abs(player.fov-desired)*.35);
if ( player.fov > desired ) player.fov -= zoom;
else player.fov += zoom;
}
}
override void CheckPoison()
{
// HAHA no
player.poisoncount = 0;
}
private void CheckBreakCrusher()
{
double gaph = (ceilingz-floorz);
if ( gaph > height*.8 ) return;
// the smaller the gap, the more likely the crusher will snap
if ( Random[Demolitionist](0,2) && (FRandom[Demolitionist](0,gaph/height) > .2) ) return;
double diffh = 8.+(default.height-gaph); // how much the crusher will have to "snap" after breaking
let ceil = ceilingsector;
let flor = floorsector;
let ceilse = ceil.ceilingdata;
let florse = flor.floordata;
if ( ceilse && florse )
{
// snap both planes
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.specialf1 = 6.;
q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.specialf1 = 6.;
SWWMCrusherBroken.Create(flor,ceil,diffh/2.);
}
else if ( ceilse )
{
// snap ceiling
let q = Spawn("BustedQuake",(ceil.centerspot.x,ceil.centerspot.y,ceil.ceilingplane.ZAtPoint(ceil.centerspot)));
q.specialf1 = 10.;
SWWMCrusherBroken.Create(null,ceil,diffh);
}
else if ( florse )
{
// snap floor
let q = Spawn("BustedQuake",(flor.centerspot.x,flor.centerspot.y,flor.floorplane.ZAtPoint(flor.centerspot)));
q.specialf1 = 10.;
SWWMCrusherBroken.Create(flor,null,diffh);
}
SWWMUtility.MarkAchievement("crush",player);
}
private void CheckBreakPolyobject( int dmg )
{
// see if there are any crushing polyobjects currently "encroaching" the player
Array<Line> touching;
BlockLinesIterator bl = BlockLinesIterator.Create(self,radius+8);
double tbox[4];
// top, bottom, left, right
tbox[0] = pos.y+(radius+8);
tbox[1] = pos.y-(radius+8);
tbox[2] = pos.x-(radius+8);
tbox[3] = pos.x+(radius+8);
foreach( l,p,f:bl )
{
if ( !l ) continue;
if ( tbox[2] > l.bbox[3] ) continue;
if ( tbox[3] < l.bbox[2] ) continue;
if ( tbox[0] < l.bbox[1] ) continue;
if ( tbox[1] > l.bbox[0] ) continue;
if ( Level.BoxOnLineSide(pos.xy,radius+8,l) != -1 ) continue;
touching.Push(l);
}
let pi = swwm_PolyobjectIterator.Create();
swwm_PolyobjectHandle p;
while ( p = pi.Next() )
{
if ( (p.Type != swwm_PolyobjectHandle.POTYP_CRUSH) && (p.Type != swwm_PolyobjectHandle.POTYP_HURT) )
continue;
foreach ( l:touching )
{
if ( p.Lines.Find(l) >= p.Lines.Size() ) continue;
Vector2 diragainst = pos.xy-p.GetPos();
double vsiz = diragainst.length();
if ( vsiz > 0 ) diragainst /= vsiz;
if ( BusterWall.BustPolyobj(p,max(dmg,(100-health)*5),self,(diragainst.x,diragainst.y,0)) )
SWWMUtility.MarkAchievement("crush",player);
if ( p.Mirror && BusterWall.BustPolyobj(p.Mirror,max(dmg,(100-health)*5),self,-(diragainst.x,diragainst.y,0)) )
SWWMUtility.MarkAchievement("crush",player);
}
}
}
override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle )
{
// we still have to ENSURE ENTIRELY that this gets nullified (TELEFRAG_DAMAGE overrides damage factors somehow)
if ( (mod == 'Falling') | (mod == 'Drowning') || (mod == 'Poison') || (mod == 'PoisonCloud') )
damage = 0;
if ( (swwm_strictuntouchable >= 2) && (damage > 0) && player )
{
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( hnd ) hnd.tookdamage[PlayerNumber()] = true;
}
if ( (mod == 'Crush') && player && (player.mo == self) )
{
// check if we can break any active crushers
// (or polyobjects)
if ( !inflictor && !source )
{
CheckBreakCrusher();
CheckBreakPolyobject(damage);
}
// break a spike trap
else if ( source is 'ThrustFloor' )
{
let q = Spawn("BustedQuake",source.pos);
q.specialf1 = 4.;
int numpt = Random[ExploS](30,40);
for ( int i=0; i<numpt; i++ )
{
let s = Spawn("SWWMChip",source.Vec3Angle(source.radius,FRandom[ExploS](0,360),1.+FRandom[ExploS](0,max(0.,source.height-source.floorclip))));
s.vel = ((0,0,1)+SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))*.6).unit()*FRandom[ExploS](2.,16.);
s.scale *= FRandom[ExploS](1.5,3.);
s.A_SetTranslation('StoneSpike');
}
numpt = Random[ExploS](12,16);
for ( int i=0; i<numpt; i++ )
{
let s = SWWMAnimSprite.SpawnAt("SWWMHalfSmoke",source.Vec3Offset(0,0,1.+FRandom[ExploS](0,max(0.,source.height-source.floorclip))));
s.vel = ((0,0,1)+SWWMUtility.Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90))).unit()*FRandom[ExploS](-2,8.);
s.scale *= 2.5;
s.framestep = Random[ExploS](4,9);
s.scolor = Color(5,4,3)*Random[ExploS](20,40);
}
Spawn("SWWMCrushedSpike",source.pos);
if ( source.master ) source.master.Destroy();
source.Destroy();
damage = 20; // reduce so it's not instant kill
SWWMUtility.MarkAchievement("kancho",player);
}
}
// no damage whatsoever
if ( scriptedinvul )
return 0;
if ( damage <= 0 ) return Super.DamageMobj(inflictor,source,damage,mod,flags,angle);
if ( !inflictor && !source && (FloorSector.flags&Sector.SECF_ENDLEVEL) )
{
// nah, man, just end the level
level.ExitLevel(0,false);
return 0;
/*// end level hax
damage = max(50,health-100);
flags |= DMG_FORCED|DMG_NO_ARMOR;
mod = 'EndLevel';*/
}
int oldpchance = PainChance;
if ( damage < 5 ) PainChance = 0;
int realdmg = Super.DamageMobj(inflictor,source,damage,mod,flags,angle);
if ( lastdamagetic != gametic )
{
lastdamage = 0;
lastdamagetimer = 0;
}
lastdamage += realdmg;
lastdamagetic = gametic;
lastdamagetimer = max(lastdamagetimer,lastdamagetic+clamp(lastdamage/2,10,40));
if ( (lastdamage > 0) && (PainChance == 0) && (level.maptime>lastmpain) )
{
lastmpain = level.maptime;
if ( player && (player.mo == self) ) A_DemoPain();
}
PainChance = oldpchance;
if ( (Health <= 0) && (source == self) && (flags&DMG_EXPLOSION) )
SWWMUtility.MarkAchievement("dime",player);
facedamage = true;
return realdmg;
}
private Vector2 BobWeaponAngle( double ticfrac )
{
// bob with player view
Vector2 prevbob = (-sin(oldbobtime*180.),.5*abs(sin(oldbobtime*180.)))*oldbob*.25;
Vector2 bob = (-sin(bobtime*180.),.5*abs(sin(bobtime*180.)))*player.bob*.25;
double bobstr = (player.WeaponState&WF_WEAPONBOBBING)?1.:player.GetWBobFire();
return SWWMUtility.LerpVector2(prevbob,bob,ticfrac)*bobstr*clamp(viewbob,0.,1.5);
}
// proper 3D weapon bob
override Vector3, Vector3 BobWeapon3D( double ticfrac )
{
if ( !player || !player.ReadyWeapon || player.ReadyWeapon.bDontBob )
return (0,0,0), (0,0,0);
bool oldbob = !!(player.WeaponState&WF_WEAPONBOBBING);
player.WeaponState |= WF_WEAPONBOBBING; // always bob
Vector2 cur = BobWeaponAngle(ticfrac);
if ( !oldbob ) player.WeaponState &= ~WF_WEAPONBOBBING;
Vector3 angles = SWWMUtility.LerpVector3(oldlagangles,lagangles,ticfrac);
Vector3 dangles = SWWMUtility.LerpVector3(oldlagdangles,lagdangles,ticfrac);
if ( abs(dangles.x) > 1. )
{
int sgn = (dangles.x>0)?1:-1;
dangles.x = abs(dangles.x)**.75*sgn;
}
if ( abs(dangles.y) > 1. )
{
int sgn = (dangles.y>0)?1:-1;
dangles.y = abs(dangles.y)**.75*sgn;
}
if ( abs(dangles.z) > 1. )
{
int sgn = (dangles.z>0)?1:-1;
dangles.z = abs(dangles.z)**.75*sgn;
}
Vector3 flagvel = SWWMUtility.LerpVector3(oldlagvel,lagvel,ticfrac);
let [x, y, z] = SWWMUtility.GetAxes(angles.x,angles.y,angles.z);
let [x2, y2, z2] = SWWMUtility.GetAxes(angles.x,0,angles.z);
double diffx = flagvel dot x;
double diffy = flagvel dot y;
double diffz = flagvel dot z;
double diffy2 = flagvel dot y2;
double diffz2 = flagvel dot z2;
if ( abs(diffx) > 1. )
{
int sgn = (diffx>0)?1:-1;
diffx = abs(diffx)**.75*sgn;
}
if ( abs(diffy) > 1. )
{
int sgn = (diffy>0)?1:-1;
diffy = abs(diffy)**.75*sgn;
}
if ( abs(diffz) > 1. )
{
int sgn = (diffz>0)?1:-1;
diffz = abs(diffz)**.75*sgn;
}
if ( abs(diffy2) > 1. )
{
int sgn = (diffy2>0)?1:-1;
diffy2 = abs(diffy2)**.75*sgn;
}
if ( abs(diffz2) > 1. )
{
int sgn = (diffz2>0)?1:-1;
diffz2 = abs(diffz2)**.75*sgn;
}
Vector3 bobvec = (diffy,-diffz,diffx*.5)*20. + (cur.x,-cur.y,cur.y)*15.;
Vector3 bobang = (dangles.x,dangles.y,dangles.z)*.15 - (cur.x,cur.y,-cur.x*2.)*.05 - (diffy2,diffz2,0)*.02;
double fready = SWWMUtility.Lerp(oldlagready,lagready,ticfrac);
double rfact = 1., vfact = 1.;
if ( player.ReadyWeapon is 'SWWMWeapon' )
{
let sw = SWWMWeapon(player.ReadyWeapon);
rfact = sw.bobfactor_ang;
vfact = sw.bobfactor_vec;
}
return bobvec*fready*vfact, bobang*fready*rfact;
}
// compatibility with 2D weapons (may cause sprite cutoff)
override Vector2 BobWeapon( double ticfrac )
{
if ( !player || !player.ReadyWeapon || player.ReadyWeapon.bDontBob )
return (0,0);
bool oldbob = !!(player.WeaponState&WF_WEAPONBOBBING);
player.WeaponState |= WF_WEAPONBOBBING; // always bob
Vector2 cur = BobWeaponAngle(ticfrac);
if ( !oldbob ) player.WeaponState &= ~WF_WEAPONBOBBING;
Vector3 angles = SWWMUtility.LerpVector3(oldlagangles,lagangles,ticfrac);
Vector3 dangles = SWWMUtility.LerpVector3(oldlagdangles,lagdangles,ticfrac);
if ( abs(dangles.x) > 1. )
{
int sgn = (dangles.x>0)?1:-1;
dangles.x = abs(dangles.x)**.75*sgn;
}
if ( abs(dangles.y) > 1. )
{
int sgn = (dangles.y>0)?1:-1;
dangles.y = abs(dangles.y)**.75*sgn;
}
cur.x += dangles.x*.4;
cur.y -= dangles.y*.4;
Vector3 flagvel = SWWMUtility.LerpVector3(oldlagvel,lagvel,ticfrac);
let [x, y, z] = SWWMUtility.GetAxes(angles.x,0,angles.z);
double diffy = flagvel dot y;
double diffz = flagvel dot z;
if ( abs(diffy) > 1. )
{
int sgn = (diffy>0)?1:-1;
diffy = abs(diffy)**.75*sgn;
}
if ( abs(diffz) > 1. )
{
int sgn = (diffz>0)?1:-1;
diffz = abs(diffz)**.75*sgn;
}
cur.x -= diffy*.4;
cur.y += diffz*.4;
return cur*SWWMUtility.Lerp(oldlagready,lagready,ticfrac);
}
override bool OnGiveSecret( bool printmsg, bool playsound )
{
if ( !player ) return false;
int score = 100;
// last secret (this is called before counting it up, so have to subtract)
if ( !hnd ) hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !deathmatch && !(gameinfo.gametype&GAME_Hexen) && (level.found_secrets == level.total_secrets-1) && (!hnd || !hnd.allsecrets) )
{
if ( hnd ) hnd.allsecrets = true;
score = 1000;
if ( player == players[consoleplayer] )
{
Console.Printf(StringTable.Localize("$SWWM_LASTSECRET"),score);
SWWMHandler.AddOneliner("findsecret",2,40);
facegrin = true;
}
else Console.Printf(StringTable.Localize("$SWWM_LASTSECRETREM"),player.GetUserName(),score);
SWWMUtility.AchievementProgressInc("allsecrets",1,player);
}
else if ( player == players[consoleplayer] )
{
Console.Printf(StringTable.Localize("$SWWM_FINDSECRET"),score);
SWWMHandler.AddOneliner("findsecret",2,40);
facegrin = true;
}
else Console.Printf(StringTable.Localize("$SWWM_FINDSECRETREM"),player.GetUserName(),score);
SWWMCredits.Give(player,score);
if ( player == players[consoleplayer] ) SWWMScoreObj.SpawnAtActorBunch(score,self);
// somehow ongivesecret can be called BEFORE PostBeginPlay (wat)
if ( !mystats ) mystats = SWWMStats.Find(player);
mystats.secrets++;
return true;
}
override bool Used( Actor user )
{
if ( !(user is 'Demolitionist') || !player || (player.mo != self) ) return false;
if ( (user.player == players[consoleplayer]) && (health > 0) )
{
SWWMHandler.AddOneliner("greet",2);
return true;
}
return false;
}
override void PreTravelled()
{
// clean up attached actors
if ( selflight ) selflight.Destroy();
if ( myshadow ) myshadow.Destroy();
// clean up our objects
SWWMItemSense si = itemsense;
while ( si )
{
let next = si.next;
si.Destroy();
si = next;
}
SWWMMagItem mi = magitem;
while ( mi )
{
let next = mi.next;
mi.Destroy();
mi = next;
}
magitem_cnt = 0;
// disable death exits
if ( player && (player.playerstate == PST_DEAD) )
{
player.cheats &= ~(CF_FROZEN|CF_TOTALLYFROZEN);
player.Resurrect();
player.damagecount = 0;
player.bonuscount = 0;
player.poisoncount = 0;
roll = 0;
if ( special1 > 2 ) special1 = 0;
}
// inventory wipes
if ( invwipe && (player.playerstate != PST_DEAD) )
{
bool wiped = false;
bool resetammo = false;
bool resetitems = false;
bool resethealth = false;
if ( invwipe&WIPE_EPISODE )
{
SWWMUtility.WipeInventory(self,swwm_resetscore);
wiped = true;
}
if ( invwipe&WIPE_CLUSTER )
{
if ( (swwm_ps_fullreset == 2) && !wiped )
{
SWWMUtility.WipeInventory(self,swwm_resetscore);
wiped = true;
}
if ( (swwm_ps_resetammo == 2) && !wiped )
{
SWWMUtility.ResetAmmo(self);
resetammo = true;
}
if ( (swwm_ps_resetitems == 2) && !wiped )
{
SWWMUtility.ResetItems(self);
resetitems = true;
}
if ( (swwm_ps_resethealth == 2) && !wiped )
{
SWWMUtility.ResetHealth(self);
resethealth = true;
}
}
if ( invwipe&WIPE_MAP )
{
if ( (swwm_ps_fullreset == 1) && !wiped )
{
SWWMUtility.WipeInventory(self,swwm_resetscore);
wiped = true;
}
if ( (swwm_ps_resetammo == 1) && !wiped && !resetammo )
SWWMUtility.ResetAmmo(self);
if ( (swwm_ps_resetitems == 1) && !wiped && !resetitems )
SWWMUtility.ResetItems(self);
if ( (swwm_ps_resethealth == 1) && !wiped && !resethealth )
SWWMUtility.ResetHealth(self);
}
}
invwipe = 0;
}
override void Travelled()
{
// reinitialize
dashfuel = default.dashfuel;
last_boost = 0;
last_kick = 0;
hasrevived = false;
blinktime = 30;
// cancel dash/boost
A_StopSound(CHAN_JETPACK);
fuelcooldown = 0.;
dashcooldown = 0.;
dashboost = 0.;
// prevent sudden stomping if we were previously falling
lastvelz = vel.z;
// clear bob data
oldlagangles = lagangles = oldangles = (angle,pitch,roll);
oldlagdangles = lagdangles = (0.,0.,0.);
oldlagvel = lagvel = vel;
bumpvelz = bumpangle = bumppitch = bumproll = 0.;
ViewAngle = ViewPitch = ViewRoll = 0.;
SetViewPos((0.,0.,0.));
// early cancel gestures
if ( player )
{
if ( player.ReadyWeapon is 'SWWMItemGesture' )
player.ReadyWeapon = SWWMItemGesture(player.ReadyWeapon).gest;
if ( player.ReadyWeapon is 'SWWMGesture' )
{
player.PendingWeapon = SWWMGesture(player.ReadyWeapon).formerweapon;
player.SetPSprite(PSP_WEAPON,player.ReadyWeapon.ResolveState("Deselect"));
}
}
}
override bool PreTeleport( Vector3 destpos, double destangle, int flags )
{
// store old pos
pretelepos = pos;
return true;
}
override void PostTeleport( Vector3 destpos, double destangle, int flags )
{
hasteleported = true; // notify tick that we teleported, so it ignores the travel distance
mystats.teledist += level.Vec3Diff(pretelepos,pos).length();
// reset all smooth bob variables if angles/velocity aren't carried over
if ( !(flags&TELF_KEEPORIENTATION) )
{
oldlagangles = lagangles = oldangles = (angle,pitch,roll);
oldlagdangles = lagdangles = (0.,0.,0.);
bumpangle = bumppitch = bumproll = 0.;
}
if ( !(flags&TELF_KEEPVELOCITY) )
{
oldlagvel = lagvel = vel;
lastvelz = vel.z;
bumpvelz = 0.;
}
// notify carried lamp that we just moved
let l = SWWMLamp(FindInventory("SWWMLamp"));
if ( l && l.thelamp )
CompanionLamp(l.thelamp).justteleport = true;
}
override void MarkPrecacheSounds()
{
Super.MarkPrecacheSounds();
MarkSound("demolitionist/walk1");
MarkSound("demolitionist/walk2");
MarkSound("demolitionist/walk3");
MarkSound("demolitionist/walk4");
MarkSound("demolitionist/runstart1");
MarkSound("demolitionist/runstart2");
MarkSound("demolitionist/runstart3");
MarkSound("demolitionist/runstart4");
MarkSound("demolitionist/run1");
MarkSound("demolitionist/run2");
MarkSound("demolitionist/run3");
MarkSound("demolitionist/run4");
MarkSound("demolitionist/runstop1");
MarkSound("demolitionist/runstop2");
MarkSound("demolitionist/runstop3");
MarkSound("demolitionist/runstop4");
MarkSound("demolitionist/jet");
MarkSound("demolitionist/jetstop");
MarkSound("demolitionist/death1");
MarkSound("demolitionist/death2");
MarkSound("demolitionist/death3");
MarkSound("demolitionist/xdeath1");
MarkSound("demolitionist/xdeath2");
MarkSound("demolitionist/xdeath3");
MarkSound("demolitionist/wdeath1");
MarkSound("demolitionist/wdeath2");
MarkSound("demolitionist/wdeath3");
MarkSound("demolitionist/pain1");
MarkSound("demolitionist/pain2");
MarkSound("demolitionist/pain3");
MarkSound("demolitionist/hipain1");
MarkSound("demolitionist/hipain2");
MarkSound("demolitionist/hipain3");
MarkSound("demolitionist/lopain1");
MarkSound("demolitionist/lopain2");
MarkSound("demolitionist/lopain3");
MarkSound("demolitionist/hardland1");
MarkSound("demolitionist/hardland2");
MarkSound("demolitionist/hardland3");
MarkSound("demolitionist/swing1");
MarkSound("demolitionist/swing2");
MarkSound("demolitionist/swing3");
MarkSound("demolitionist/wswing1");
MarkSound("demolitionist/wswing2");
MarkSound("demolitionist/punch1");
MarkSound("demolitionist/punch2");
MarkSound("demolitionist/punch3");
MarkSound("demolitionist/punchf1");
MarkSound("demolitionist/punchf2");
MarkSound("demolitionist/punchf3");
MarkSound("demolitionist/bump1");
MarkSound("demolitionist/bump2");
MarkSound("demolitionist/bump3");
MarkSound("demolitionist/kick1");
MarkSound("demolitionist/kick2");
MarkSound("demolitionist/kick3");
MarkSound("demolitionist/revive");
MarkSound("demolitionist/youdied");
MarkSound("demolitionist/parry");
MarkSound("demolitionist/handsup");
MarkSound("demolitionist/handsdown");
MarkSound("demolitionist/whits1");
MarkSound("demolitionist/whits2");
MarkSound("demolitionist/whits3");
MarkSound("demolitionist/whitm1");
MarkSound("demolitionist/whitm2");
MarkSound("demolitionist/whitm3");
MarkSound("demolitionist/whitl1");
MarkSound("demolitionist/whitl2");
MarkSound("demolitionist/buttslam1");
MarkSound("demolitionist/buttslam2");
MarkSound("demolitionist/buttslam3");
MarkSound("demolitionist/buttslamx");
MarkSound("demolitionist/petting");
MarkSound("demolitionist/knockout");
}
}