2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#include "names2.h"
|
2020-08-05 22:18:45 +00:00
|
|
|
#include "misc.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "tags.h"
|
|
|
|
#include "ai.h"
|
|
|
|
#include "weapon.h"
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int InitSpriteGrenade(DSWActor* actor);
|
2021-11-01 09:59:10 +00:00
|
|
|
int InitSpriteChemBomb(DSWActor*);
|
2021-10-29 18:49:57 +00:00
|
|
|
int InitFlashBomb(DSWActor* actor);
|
2021-11-01 10:50:50 +00:00
|
|
|
int InitCaltrops(DSWActor* actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// SKULL Wait
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
extern DAMAGE_DATA DamageData[];
|
2021-10-29 18:49:57 +00:00
|
|
|
ANIMATOR DoSkullMove,DoActorDebris;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#define SKULL_RATE 10
|
|
|
|
ANIMATOR DoSkullWait;
|
|
|
|
|
|
|
|
STATE s_SkullWait[5][1] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{SKULL_R0 + 0, SKULL_RATE, DoSkullWait, &s_SkullWait[0][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R1 + 0, SKULL_RATE, DoSkullWait, &s_SkullWait[1][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R2 + 0, SKULL_RATE, DoSkullWait, &s_SkullWait[2][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R3 + 0, SKULL_RATE, DoSkullWait, &s_SkullWait[3][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R4 + 0, SKULL_RATE, DoSkullWait, &s_SkullWait[4][0]},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_SkullWait[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
&s_SkullWait[0][0],
|
|
|
|
&s_SkullWait[1][0],
|
|
|
|
&s_SkullWait[2][0],
|
|
|
|
&s_SkullWait[3][0],
|
|
|
|
&s_SkullWait[4][0]
|
|
|
|
};
|
|
|
|
|
|
|
|
ATTRIBUTE SkullAttrib =
|
|
|
|
{
|
|
|
|
{60, 80, 100, 130}, // Speeds
|
|
|
|
{3, 0, -2, -3}, // Tic Adjusts
|
|
|
|
3, // MaxWeapons;
|
|
|
|
{
|
|
|
|
DIGI_AHAMBIENT, 0, 0, 0, DIGI_AHSCREAM,
|
|
|
|
DIGI_AHEXPLODE,0,0,0,0
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// SKULL for Serp God
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
ANIMATOR DoSerpRing;
|
|
|
|
|
|
|
|
STATE s_SkullRing[5][1] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{SKULL_R0 + 0, SKULL_RATE, DoSerpRing, &s_SkullRing[0][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R1 + 0, SKULL_RATE, DoSerpRing, &s_SkullRing[1][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R2 + 0, SKULL_RATE, DoSerpRing, &s_SkullRing[2][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R3 + 0, SKULL_RATE, DoSerpRing, &s_SkullRing[3][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R4 + 0, SKULL_RATE, DoSerpRing, &s_SkullRing[4][0]},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_SkullRing[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
&s_SkullRing[0][0],
|
|
|
|
&s_SkullRing[1][0],
|
|
|
|
&s_SkullRing[2][0],
|
|
|
|
&s_SkullRing[3][0],
|
|
|
|
&s_SkullRing[4][0]
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// SKULL Jump
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
ANIMATOR DoSkullJump;
|
|
|
|
|
|
|
|
STATE s_SkullJump[5][1] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{SKULL_R0 + 0, SKULL_RATE, DoSkullJump, &s_SkullJump[0][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R1 + 0, SKULL_RATE, DoSkullJump, &s_SkullJump[1][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R2 + 0, SKULL_RATE, DoSkullJump, &s_SkullJump[2][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R3 + 0, SKULL_RATE, DoSkullJump, &s_SkullJump[3][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{SKULL_R4 + 0, SKULL_RATE, DoSkullJump, &s_SkullJump[4][0]},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_SkullJump[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
&s_SkullJump[0][0],
|
|
|
|
&s_SkullJump[1][0],
|
|
|
|
&s_SkullJump[2][0],
|
|
|
|
&s_SkullJump[3][0],
|
|
|
|
&s_SkullJump[4][0]
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// SKULL Explode
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
#define SKULL_EXPLODE_RATE 11
|
|
|
|
ANIMATOR DoSuicide;
|
|
|
|
ANIMATOR DoSkullSpawnShrap;
|
|
|
|
|
|
|
|
STATE s_SkullExplode[] =
|
|
|
|
{
|
|
|
|
{SKULL_EXPLODE + 0, 1, NullAnimator, &s_SkullExplode[1]},
|
|
|
|
{SKULL_EXPLODE + 0, SF_QUICK_CALL, DoDamageTest, &s_SkullExplode[2]},
|
|
|
|
{SKULL_EXPLODE + 0, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[3]},
|
|
|
|
{SKULL_EXPLODE + 1, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[4]},
|
|
|
|
{SKULL_EXPLODE + 2, SF_QUICK_CALL, DoSkullSpawnShrap, &s_SkullExplode[5]},
|
|
|
|
{SKULL_EXPLODE + 2, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[6]},
|
|
|
|
{SKULL_EXPLODE + 3, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[7]},
|
|
|
|
{SKULL_EXPLODE + 4, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[8]},
|
|
|
|
{SKULL_EXPLODE + 5, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[9]},
|
|
|
|
{SKULL_EXPLODE + 6, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[10]},
|
|
|
|
{SKULL_EXPLODE + 7, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[11]},
|
|
|
|
{SKULL_EXPLODE + 8, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[12]},
|
|
|
|
{SKULL_EXPLODE + 9, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[13]},
|
|
|
|
{SKULL_EXPLODE +10, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[14]},
|
|
|
|
{SKULL_EXPLODE +11, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[15]},
|
|
|
|
{SKULL_EXPLODE +12, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[16]},
|
|
|
|
{SKULL_EXPLODE +13, SKULL_EXPLODE_RATE, NullAnimator, &s_SkullExplode[17]},
|
|
|
|
{SKULL_EXPLODE +13, SKULL_EXPLODE_RATE, DoSuicide, &s_SkullExplode[17]}
|
|
|
|
};
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_SkullExplode[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
s_SkullExplode,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int SetupSkull(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ANIMATOR DoActorDecide;
|
|
|
|
|
2021-12-27 19:22:21 +00:00
|
|
|
if (!(actor->spr.cstat & CSTAT_SPRITE_RESTORE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 21:34:06 +00:00
|
|
|
SpawnUser(actor,SKULL_R0,s_SkullWait[0]);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Health = HEALTH_SKULL;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-30 18:11:31 +00:00
|
|
|
ChangeState(actor, s_SkullWait[0]);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Attrib = &SkullAttrib;
|
2021-10-30 10:09:34 +00:00
|
|
|
DoActorSetSpeed(actor, NORM_SPEED);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.StateEnd = s_SkullExplode;
|
|
|
|
actor->user.Rot = sg_SkullWait;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.ID = SKULL_R0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 20:17:31 +00:00
|
|
|
EnemyDefaults(actor, nullptr, nullptr);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.clipdist = (128+64) >> 2;
|
2021-12-27 16:13:47 +00:00
|
|
|
actor->user.Flags |= (SPR_XFLIP_TOGGLE);
|
|
|
|
actor->spr.cstat |= (CSTAT_SPRITE_YCENTER);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Radius = 400;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-21 08:06:31 +00:00
|
|
|
if (ActorZOfBottom(actor) > actor->user.loz - 16)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2022-08-20 20:49:30 +00:00
|
|
|
actor->spr.pos.Z = actor->user.loz + tileTopOffset(actor->spr.picnum);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-20 20:06:00 +00:00
|
|
|
actor->user.loz = actor->spr.pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
// leave 8 pixels above the ground
|
2022-02-01 19:19:46 +00:00
|
|
|
actor->add_int_z(ActorSizeToTop(actor) - Z(3));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Counter = RANDOM_P2(2048);
|
2022-08-21 07:25:15 +00:00
|
|
|
actor->user.pos.Z = actor->spr.pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int DoSkullMove(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
int32_t dax, day, daz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-16 21:15:49 +00:00
|
|
|
dax = MOVEx(actor->spr.xvel, actor->int_ang());
|
|
|
|
day = MOVEy(actor->spr.xvel, actor->int_ang());
|
2021-12-24 15:47:29 +00:00
|
|
|
daz = actor->spr.zvel;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.coll = move_missile(actor, dax, day, daz, Z(16), Z(16), CLIPMASK_MISSILE, ACTORMOVETICS);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-30 22:01:08 +00:00
|
|
|
DoFindGroundPoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int DoSkullBeginDeath(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
int16_t i,num_ord=0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Decrease for Serp God
|
2021-11-02 23:14:09 +00:00
|
|
|
auto own = GetOwner(actor);
|
|
|
|
if (own != nullptr && own->hasU())
|
2021-12-23 22:45:39 +00:00
|
|
|
own->user.Counter--;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// starts the explosion that does the actual damage
|
|
|
|
|
2021-12-24 15:47:29 +00:00
|
|
|
switch (actor->spr.hitag)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
case 1:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 2;
|
|
|
|
if (num_ord > 3) num_ord = 3;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:27:44 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (i*1024)));
|
2021-11-01 09:59:10 +00:00
|
|
|
InitSpriteChemBomb(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 5;
|
|
|
|
if (num_ord > 10) num_ord = 10;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(RandomRange(2048)));
|
2021-11-01 10:50:50 +00:00
|
|
|
InitCaltrops(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
InitFlashBomb(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 5;
|
|
|
|
if (num_ord > 10) num_ord = 10;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->spr.int_ang() + (i * (2048 / num_ord))));
|
2021-10-29 18:49:57 +00:00
|
|
|
InitSpriteGrenade(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2021-11-04 23:16:01 +00:00
|
|
|
SpawnMineExp(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
for (i=0; i<3; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(RandomRange(2048)));
|
2021-11-01 10:50:50 +00:00
|
|
|
InitPhosphorus(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-27 17:58:15 +00:00
|
|
|
actor->spr.cstat &= ~(CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.RotNum = 0;
|
|
|
|
actor->user.Tics = 0;
|
|
|
|
actor->user.ID = SKULL_R0;
|
|
|
|
actor->user.Radius = DamageData[DMG_SKULL_EXP].radius; //*DamageRadiusSkull;
|
|
|
|
actor->user.OverlapZ = Z(64);
|
2021-10-30 18:00:02 +00:00
|
|
|
change_actor_stat(actor, STAT_DEAD_ACTOR);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.shade = -40;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-04 23:13:44 +00:00
|
|
|
SpawnLittleExp(actor);
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoSkullJump(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.xvel)
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullMove(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (64 * ACTORMOVETICS)));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-27 18:34:06 +00:00
|
|
|
if (actor->user.Flags & (SPR_JUMPING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 21:38:21 +00:00
|
|
|
DoJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-12-27 18:34:06 +00:00
|
|
|
else if (actor->user.Flags & (SPR_FALLING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 21:41:33 +00:00
|
|
|
DoFall(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// jump/fall type
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.xvel)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
int dist,a,b,c;
|
|
|
|
|
2022-02-01 23:08:21 +00:00
|
|
|
DISTANCE(actor->int_pos().X, actor->int_pos().Y, actor->user.targetActor->int_pos().X, actor->user.targetActor->int_pos().Y, dist, a, b, c);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dist < 1000 &&
|
2021-12-25 21:32:56 +00:00
|
|
|
SpriteOverlapZ(actor, actor->user.targetActor, Z(32)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-20 20:49:30 +00:00
|
|
|
if (actor->spr.pos.Z > actor->user.loz - 36)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2022-08-20 20:49:30 +00:00
|
|
|
actor->spr.pos.Z = actor->user.loz - 36;
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// non jumping type
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
if (actor->user.jump_speed > 200)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoSkullBob(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
// actor does a sine wave about actor->user.sz - this is the z mid point
|
2021-11-02 20:58:34 +00:00
|
|
|
const int SKULL_BOB_AMT = (Z(16));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Counter = (actor->user.Counter + (ACTORMOVETICS << 3) + (ACTORMOVETICS << 1)) & 2047;
|
2022-08-21 06:23:20 +00:00
|
|
|
actor->set_int_z(actor->user.int_upos().Z + MulScale(SKULL_BOB_AMT, bsin(actor->user.Counter), 14) +
|
2022-02-01 19:04:41 +00:00
|
|
|
MulScale((SKULL_BOB_AMT / 2), bsin(actor->user.Counter), 14));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoSkullSpawnShrap(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:44:51 +00:00
|
|
|
SpawnShrap(actor, nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 09:54:52 +00:00
|
|
|
//PlaySpriteSound(actor,attr_extra1,v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoSkullWait(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int a,b,c,dist;
|
|
|
|
|
2022-02-01 23:08:21 +00:00
|
|
|
DISTANCE(actor->int_pos().X, actor->int_pos().Y, actor->user.targetActor->int_pos().X, actor->user.targetActor->int_pos().Y, dist, a, b, c);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-30 11:05:07 +00:00
|
|
|
DoActorPickClosePlayer(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
//if (dist < actor->user.active_range)
|
2015-05-19 21:54:34 +00:00
|
|
|
// return(0);
|
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
if ((actor->user.WaitTics -= ACTORMOVETICS) <= 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_AHSCREAM, actor, v3df_none);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.WaitTics = SEC(3) + RandomRange(360);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// below the floor type
|
2022-08-20 20:49:30 +00:00
|
|
|
if (actor->spr.pos.Z > actor->user.loz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// look for closest player every once in a while
|
|
|
|
if (dist < 3500)
|
|
|
|
{
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.xvel = 0;
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.jump_speed = -600;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, sg_SkullJump);
|
2021-10-29 21:03:47 +00:00
|
|
|
DoBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// above the floor type
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (48 * ACTORMOVETICS)));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoSkullBob(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dist < 8000)
|
|
|
|
{
|
2022-08-20 19:14:00 +00:00
|
|
|
actor->spr.angle = VecToAngle(actor->user.targetActor->spr.pos - actor->spr.pos);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.xvel = 128 + (RANDOM_P2(256<<8)>>8);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.jump_speed = -700;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, sg_SkullJump);
|
2021-10-29 21:03:47 +00:00
|
|
|
DoBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// BETTY Wait
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
ANIMATOR DoBettyMove,DoActorDebris;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#define BETTY_RATE 10
|
|
|
|
ANIMATOR DoBettyWait;
|
|
|
|
|
|
|
|
STATE s_BettyWait[5][3] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{BETTY_R0 + 0, BETTY_RATE, DoBettyWait, &s_BettyWait[0][1]},
|
|
|
|
{BETTY_R0 + 1, BETTY_RATE, DoBettyWait, &s_BettyWait[0][2]},
|
|
|
|
{BETTY_R0 + 2, BETTY_RATE, DoBettyWait, &s_BettyWait[0][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R1 + 0, BETTY_RATE, DoBettyWait, &s_BettyWait[1][1]},
|
|
|
|
{BETTY_R1 + 1, BETTY_RATE, DoBettyWait, &s_BettyWait[1][2]},
|
|
|
|
{BETTY_R1 + 2, BETTY_RATE, DoBettyWait, &s_BettyWait[1][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R2 + 0, BETTY_RATE, DoBettyWait, &s_BettyWait[2][1]},
|
|
|
|
{BETTY_R2 + 1, BETTY_RATE, DoBettyWait, &s_BettyWait[2][2]},
|
|
|
|
{BETTY_R2 + 2, BETTY_RATE, DoBettyWait, &s_BettyWait[2][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R3 + 0, BETTY_RATE, DoBettyWait, &s_BettyWait[3][1]},
|
|
|
|
{BETTY_R3 + 1, BETTY_RATE, DoBettyWait, &s_BettyWait[3][2]},
|
|
|
|
{BETTY_R3 + 2, BETTY_RATE, DoBettyWait, &s_BettyWait[3][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R4 + 0, BETTY_RATE, DoBettyWait, &s_BettyWait[4][1]},
|
|
|
|
{BETTY_R4 + 1, BETTY_RATE, DoBettyWait, &s_BettyWait[4][2]},
|
|
|
|
{BETTY_R4 + 2, BETTY_RATE, DoBettyWait, &s_BettyWait[4][0]},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_BettyWait[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
&s_BettyWait[0][0],
|
|
|
|
&s_BettyWait[1][0],
|
|
|
|
&s_BettyWait[2][0],
|
|
|
|
&s_BettyWait[3][0],
|
|
|
|
&s_BettyWait[4][0]
|
|
|
|
};
|
|
|
|
|
|
|
|
ATTRIBUTE BettyAttrib =
|
|
|
|
{
|
|
|
|
{60, 80, 100, 130}, // Speeds
|
|
|
|
{3, 0, -2, -3}, // Tic Adjusts
|
|
|
|
3, // MaxWeapons;
|
|
|
|
{0, 0, 0, 0, 0, 0,0,0,0,0}
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// BETTY Jump
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
ANIMATOR DoBettyJump;
|
|
|
|
|
|
|
|
STATE s_BettyJump[5][1] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
{BETTY_R0 + 0, BETTY_RATE, DoBettyJump, &s_BettyJump[0][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R1 + 0, BETTY_RATE, DoBettyJump, &s_BettyJump[1][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R2 + 0, BETTY_RATE, DoBettyJump, &s_BettyJump[2][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R3 + 0, BETTY_RATE, DoBettyJump, &s_BettyJump[3][0]},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{BETTY_R4 + 0, BETTY_RATE, DoBettyJump, &s_BettyJump[4][0]},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_BettyJump[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
&s_BettyJump[0][0],
|
|
|
|
&s_BettyJump[1][0],
|
|
|
|
&s_BettyJump[2][0],
|
|
|
|
&s_BettyJump[3][0],
|
|
|
|
&s_BettyJump[4][0]
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// BETTY Explode
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
#define BETTY_EXPLODE_RATE 11
|
|
|
|
#define BETTY_EXPLODE BETTY_R0
|
|
|
|
ANIMATOR DoSuicide;
|
|
|
|
ANIMATOR DoBettySpawnShrap;
|
|
|
|
|
|
|
|
STATE s_BettyExplode[] =
|
|
|
|
{
|
|
|
|
{BETTY_EXPLODE + 0, SF_QUICK_CALL, DoDamageTest, &s_BettyExplode[1]},
|
|
|
|
{BETTY_EXPLODE + 0, BETTY_EXPLODE_RATE, DoSuicide, &s_BettyExplode[0]}
|
|
|
|
};
|
|
|
|
|
2021-12-31 15:00:14 +00:00
|
|
|
STATE* sg_BettyExplode[] =
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
s_BettyExplode,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int SetupBetty(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ANIMATOR DoActorDecide;
|
|
|
|
|
2021-12-27 19:22:21 +00:00
|
|
|
if (!(actor->spr.cstat & CSTAT_SPRITE_RESTORE))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 21:34:06 +00:00
|
|
|
SpawnUser(actor,BETTY_R0,s_BettyWait[0]);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Health = HEALTH_SKULL;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-30 18:11:31 +00:00
|
|
|
ChangeState(actor, s_BettyWait[0]);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Attrib = &BettyAttrib;
|
2021-10-30 10:09:34 +00:00
|
|
|
DoActorSetSpeed(actor, NORM_SPEED);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.StateEnd = s_BettyExplode;
|
|
|
|
actor->user.Rot = sg_BettyWait;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.ID = BETTY_R0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 20:17:31 +00:00
|
|
|
EnemyDefaults(actor, nullptr, nullptr);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.clipdist = (128+64) >> 2;
|
2021-12-27 16:13:47 +00:00
|
|
|
actor->user.Flags |= (SPR_XFLIP_TOGGLE);
|
|
|
|
actor->spr.cstat |= (CSTAT_SPRITE_YCENTER);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Radius = 400;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-21 08:06:31 +00:00
|
|
|
if (ActorZOfBottom(actor) > actor->user.loz - 16)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2022-08-20 20:49:30 +00:00
|
|
|
actor->spr.pos.Z = actor->user.loz + tileTopOffset(actor->spr.picnum);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-20 20:06:00 +00:00
|
|
|
actor->user.loz = actor->spr.pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
// leave 8 pixels above the ground
|
2022-02-01 19:19:46 +00:00
|
|
|
actor->add_int_z(ActorSizeToTop(actor) - Z(3));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Counter = RANDOM_P2(2048);
|
2022-08-21 07:25:15 +00:00
|
|
|
actor->user.pos.Z = actor->spr.pos.Z;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int DoBettyMove(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
int32_t dax, day, daz;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2022-08-16 21:15:49 +00:00
|
|
|
dax = MOVEx(actor->spr.xvel, actor->int_ang());
|
|
|
|
day = MOVEy(actor->spr.xvel, actor->int_ang());
|
2021-12-24 15:47:29 +00:00
|
|
|
daz = actor->spr.zvel;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.coll = move_missile(actor, dax, day, daz, Z(16), Z(16), CLIPMASK_MISSILE, ACTORMOVETICS);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-30 22:01:08 +00:00
|
|
|
DoFindGroundPoint(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-02 20:58:34 +00:00
|
|
|
int DoBettyBeginDeath(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
int16_t i,num_ord=0;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// starts the explosion that does the actual damage
|
|
|
|
|
2021-12-24 15:47:29 +00:00
|
|
|
switch (actor->spr.hitag)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
case 1:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 2;
|
|
|
|
if (num_ord > 3) num_ord = 3;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:27:44 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (i*1024)));
|
2021-11-01 09:59:10 +00:00
|
|
|
InitSpriteChemBomb(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 5;
|
|
|
|
if (num_ord > 10) num_ord = 10;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(RandomRange(2048)));
|
2021-11-01 10:50:50 +00:00
|
|
|
InitCaltrops(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
2021-10-29 18:49:57 +00:00
|
|
|
InitFlashBomb(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.lotag) num_ord = actor->spr.lotag;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
num_ord = 5;
|
|
|
|
if (num_ord > 10) num_ord = 10;
|
|
|
|
for (i=0; i<num_ord; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (i*(2048/num_ord))));
|
2021-10-29 18:49:57 +00:00
|
|
|
InitSpriteGrenade(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for (i=0; i<5; i++)
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(RandomRange(2048)));
|
2021-11-01 10:50:50 +00:00
|
|
|
InitPhosphorus(actor);
|
2021-11-04 23:16:01 +00:00
|
|
|
SpawnMineExp(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-12-27 17:58:15 +00:00
|
|
|
actor->spr.cstat &= ~(CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.RotNum = 0;
|
|
|
|
actor->user.Tics = 0;
|
|
|
|
actor->user.ID = BETTY_R0;
|
|
|
|
actor->user.Radius = DamageData[DMG_SKULL_EXP].radius; //*DamageRadiusBetty;
|
|
|
|
actor->user.OverlapZ = Z(64);
|
2021-10-30 18:00:02 +00:00
|
|
|
change_actor_stat(actor, STAT_DEAD_ACTOR);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.shade = -40;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-04 23:13:44 +00:00
|
|
|
SpawnLittleExp(actor);
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoBettyJump(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.xvel)
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyMove(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (64 * ACTORMOVETICS)));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-27 18:34:06 +00:00
|
|
|
if (actor->user.Flags & (SPR_JUMPING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 21:38:21 +00:00
|
|
|
DoJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-12-27 18:34:06 +00:00
|
|
|
else if (actor->user.Flags & (SPR_FALLING))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 21:41:33 +00:00
|
|
|
DoFall(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// jump/fall type
|
2021-12-24 15:47:29 +00:00
|
|
|
if (actor->spr.xvel)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int dist,a,b,c;
|
|
|
|
|
2022-02-01 23:08:21 +00:00
|
|
|
DISTANCE(actor->int_pos().X, actor->int_pos().Y, actor->user.targetActor->int_pos().X, actor->user.targetActor->int_pos().Y, dist, a, b, c);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dist < 1000 &&
|
2021-12-25 21:32:56 +00:00
|
|
|
SpriteOverlapZ(actor, actor->user.targetActor, Z(32)))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-08-20 20:49:30 +00:00
|
|
|
if (actor->spr.pos.Z > actor->user.loz - 36)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2022-08-20 20:49:30 +00:00
|
|
|
actor->spr.pos.Z = actor->user.loz - 36;
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// non jumping type
|
|
|
|
else
|
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
if (actor->user.jump_speed > 200)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-10-30 19:07:15 +00:00
|
|
|
UpdateSinglePlayKills(actor);
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyBeginDeath(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoBettyBob(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-12-25 21:32:56 +00:00
|
|
|
// actor does a sine wave about actor->user.sz - this is the z mid point
|
2021-11-02 20:58:34 +00:00
|
|
|
const int BETTY_BOB_AMT = (Z(16));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.Counter = (actor->user.Counter + (ACTORMOVETICS << 3) + (ACTORMOVETICS << 1)) & 2047;
|
2022-08-21 06:23:20 +00:00
|
|
|
actor->set_int_z(actor->user.int_upos().Z + MulScale(BETTY_BOB_AMT, bsin(actor->user.Counter), 14) +
|
2022-02-01 19:04:41 +00:00
|
|
|
MulScale((BETTY_BOB_AMT / 2), bsin(actor->user.Counter), 14));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoBettySpawnShrap(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 19:44:51 +00:00
|
|
|
SpawnShrap(actor, nullptr);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int DoBettyWait(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
int a,b,c,dist;
|
|
|
|
|
2022-02-01 23:08:21 +00:00
|
|
|
DISTANCE(actor->int_pos().X, actor->int_pos().Y, actor->user.targetActor->int_pos().X, actor->user.targetActor->int_pos().Y, dist, a, b, c);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-30 11:05:07 +00:00
|
|
|
DoActorPickClosePlayer(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-12-25 21:32:56 +00:00
|
|
|
if ((actor->user.WaitTics -= ACTORMOVETICS) <= 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_none);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.WaitTics = SEC(3);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// below the floor type
|
2022-08-20 20:49:30 +00:00
|
|
|
if (actor->spr.pos.Z > actor->user.loz)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// look for closest player every once in a while
|
|
|
|
if (dist < 3500)
|
|
|
|
{
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.xvel = 0;
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.jump_speed = -600;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, sg_BettyJump);
|
2021-10-29 21:03:47 +00:00
|
|
|
DoBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// above the floor type
|
|
|
|
{
|
2022-08-16 21:23:42 +00:00
|
|
|
actor->set_int_ang(NORM_ANGLE(actor->int_ang() + (48 * ACTORMOVETICS)));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DoBettyBob(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dist < 8000)
|
|
|
|
{
|
2022-08-20 19:14:00 +00:00
|
|
|
actor->spr.angle = VecToAngle(actor->user.targetActor->spr.pos - actor->spr.pos);
|
2021-12-24 15:47:29 +00:00
|
|
|
actor->spr.xvel = 128 + (RANDOM_P2(256<<8)>>8);
|
2021-12-25 21:32:56 +00:00
|
|
|
actor->user.jump_speed = -700;
|
2021-10-30 21:12:31 +00:00
|
|
|
NewStateGroup(actor, sg_BettyJump);
|
2021-10-29 21:03:47 +00:00
|
|
|
DoBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "saveable.h"
|
|
|
|
|
|
|
|
static saveable_code saveable_skull_code[] =
|
|
|
|
{
|
|
|
|
SAVE_CODE(DoSkullMove),
|
|
|
|
SAVE_CODE(DoSkullBeginDeath),
|
|
|
|
SAVE_CODE(DoSkullJump),
|
|
|
|
SAVE_CODE(DoSkullBob),
|
|
|
|
SAVE_CODE(DoSkullSpawnShrap),
|
|
|
|
SAVE_CODE(DoSkullWait),
|
|
|
|
|
|
|
|
SAVE_CODE(DoBettyMove),
|
|
|
|
SAVE_CODE(DoBettyBeginDeath),
|
|
|
|
SAVE_CODE(DoBettyJump),
|
|
|
|
SAVE_CODE(DoBettyBob),
|
|
|
|
SAVE_CODE(DoBettySpawnShrap),
|
|
|
|
SAVE_CODE(DoBettyWait),
|
|
|
|
};
|
|
|
|
|
|
|
|
static saveable_data saveable_skull_data[] =
|
|
|
|
{
|
|
|
|
SAVE_DATA(s_SkullWait),
|
|
|
|
SAVE_DATA(sg_SkullWait),
|
|
|
|
|
|
|
|
SAVE_DATA(SkullAttrib),
|
|
|
|
|
|
|
|
SAVE_DATA(s_SkullRing),
|
|
|
|
SAVE_DATA(sg_SkullRing),
|
|
|
|
SAVE_DATA(s_SkullJump),
|
|
|
|
SAVE_DATA(sg_SkullJump),
|
|
|
|
SAVE_DATA(s_SkullExplode),
|
|
|
|
SAVE_DATA(sg_SkullExplode),
|
|
|
|
SAVE_DATA(s_BettyWait),
|
|
|
|
SAVE_DATA(sg_BettyWait),
|
|
|
|
|
|
|
|
SAVE_DATA(BettyAttrib),
|
|
|
|
|
|
|
|
SAVE_DATA(s_BettyJump),
|
|
|
|
SAVE_DATA(sg_BettyJump),
|
|
|
|
SAVE_DATA(s_BettyExplode),
|
|
|
|
SAVE_DATA(sg_BettyExplode),
|
|
|
|
};
|
|
|
|
|
|
|
|
saveable_module saveable_skull =
|
|
|
|
{
|
|
|
|
// code
|
|
|
|
saveable_skull_code,
|
|
|
|
SIZ(saveable_skull_code),
|
|
|
|
|
|
|
|
// data
|
|
|
|
saveable_skull_data,
|
|
|
|
SIZ(saveable_skull_data)
|
|
|
|
};
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|