mirror of
https://github.com/DrBeef/Raze.git
synced 2025-03-21 00:40:51 +00:00
- scriptified the trip bombs.
This commit is contained in:
parent
133cb3a02e
commit
8ce358fc24
19 changed files with 438 additions and 235 deletions
|
@ -43,6 +43,7 @@ struct FActorInfo
|
|||
int TypeNum = -1;
|
||||
int DefaultFlags = 0;
|
||||
int DefaultCstat = 0;
|
||||
int Health = 0; // not used yet - this will stand in if no CON defines a health value for Duke.
|
||||
spritetype defsprite{}; // Due to how the map format works we cannot define defaults for the sprite itself. These must be applied later.
|
||||
|
||||
// these are temporary. Due to how Build games handle their tiles, we cannot look up the textures when scripts are being parsed.
|
||||
|
|
|
@ -500,3 +500,12 @@ DEFINE_PROPERTY(spriteset, Sssssssssssssssssssssssssssssss, CoreActor)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_PROPERTY(health, I, CoreActor)
|
||||
{
|
||||
PROP_INT_PARM(i, 0);
|
||||
bag.Info->ActorInfo()->Health = i;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,22 @@
|
|||
#include "vm.h"
|
||||
#include "gamefuncs.h"
|
||||
|
||||
sectortype* Raze_updatesector(double x, double y, sectortype* sec, double dist)
|
||||
{
|
||||
updatesector(DVector2(x, y), &sec, dist);
|
||||
return sec;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Raze, updatesector, Raze_updatesector)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_POINTER(s, sectortype);
|
||||
PARAM_FLOAT(dist);
|
||||
ACTION_RETURN_POINTER(Raze_updatesector(x, y, s, dist));
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// internal sector struct - no longer identical with on-disk format
|
||||
|
@ -101,6 +117,7 @@ DEFINE_FIELD_X(tspritetype, tspritetype, xoffset)
|
|||
DEFINE_FIELD_X(tspritetype, tspritetype, yoffset)
|
||||
DEFINE_FIELD_X(tspritetype, tspritetype, ownerActor)
|
||||
DEFINE_FIELD_X(tspritetype, tspritetype, time)
|
||||
DEFINE_FIELD_X(tspritetype, tspritetype, pos)
|
||||
|
||||
DEFINE_GLOBAL_NAMED(wall, walls)
|
||||
DEFINE_GLOBAL_NAMED(sector, sectors)
|
||||
|
@ -691,5 +708,3 @@ DEFINE_ACTION_FUNCTION_NATIVE(DCoreActor, setpositionz, coreactor_setpositionz)
|
|||
coreactor_setpositionz(self, x, y, z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -800,163 +800,6 @@ void movefallers_d(void)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void movetripbomb(DDukeActor *actor)
|
||||
{
|
||||
int j;
|
||||
double x;
|
||||
int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, nullptr, -1).safeValue();
|
||||
if (lTripBombControl & TRIPBOMB_TIMER)
|
||||
{
|
||||
// we're on a timer....
|
||||
if (actor->spr.extra >= 0)
|
||||
{
|
||||
actor->spr.extra--;
|
||||
if (actor->spr.extra == 0)
|
||||
{
|
||||
actor->temp_data[2] = 16;
|
||||
S_PlayActorSound(LASERTRIP_ARMING, actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actor->temp_data[2] > 0)
|
||||
{
|
||||
actor->temp_data[2]--;
|
||||
if (actor->temp_data[2] == 8)
|
||||
{
|
||||
S_PlayActorSound(LASERTRIP_EXPLODE, actor);
|
||||
for (j = 0; j < 5; j++) RANDOMSCRAP(actor);
|
||||
int ex = actor->spr.extra;
|
||||
fi.hitradius(actor, gs.tripbombblastradius, ex >> 2, ex >> 1, ex - (ex >> 2), ex);
|
||||
|
||||
auto spawned = spawn(actor, EXPLOSION2);
|
||||
if (spawned)
|
||||
{
|
||||
spawned->spr.angle = actor->spr.angle;
|
||||
spawned->vel.X = 348 / 16.;
|
||||
ssp(spawned, CLIPMASK0);
|
||||
}
|
||||
|
||||
DukeStatIterator it(STAT_MISC);
|
||||
while (auto a1 = it.Next())
|
||||
{
|
||||
if (a1->spr.picnum == LASERLINE && actor->spr.hitag == a1->spr.hitag)
|
||||
a1->spr.scale = DVector2(0, 0);
|
||||
}
|
||||
deletesprite(actor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ex = actor->spr.extra;
|
||||
actor->spr.extra = 1;
|
||||
auto ang = actor->spr.angle;
|
||||
j = fi.ifhitbyweapon(actor);
|
||||
if (j >= 0)
|
||||
{
|
||||
actor->temp_data[2] = 16;
|
||||
}
|
||||
actor->spr.extra = ex;
|
||||
actor->spr.angle = ang;
|
||||
}
|
||||
|
||||
if (actor->temp_data[0] < 32)
|
||||
{
|
||||
findplayer(actor, &x);
|
||||
if (x > 48) actor->temp_data[0]++;
|
||||
else if (actor->temp_data[0] > 16) actor->temp_data[0]++;
|
||||
}
|
||||
if (actor->temp_data[0] == 32)
|
||||
{
|
||||
auto ang = actor->spr.angle;
|
||||
actor->spr.angle = actor->temp_angle;
|
||||
|
||||
actor->temp_pos = actor->spr.pos;
|
||||
actor->spr.pos += actor->temp_angle.ToVector() * 2;
|
||||
actor->spr.pos.Z -= 3;
|
||||
|
||||
// Laser fix from EDuke32.
|
||||
auto const oldSect = actor->sector();
|
||||
auto curSect = actor->sector();
|
||||
|
||||
updatesector(actor->spr.pos, &curSect, 128);
|
||||
ChangeActorSect(actor, curSect);
|
||||
|
||||
DDukeActor* hit;
|
||||
x = hitasprite(actor, &hit);
|
||||
|
||||
actor->ovel.X = x;
|
||||
|
||||
actor->spr.angle = ang;
|
||||
|
||||
if (lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
// we're on a trip wire
|
||||
while (x > 0)
|
||||
{
|
||||
auto spawned = spawn(actor, LASERLINE);
|
||||
if (spawned)
|
||||
{
|
||||
SetActor(spawned, spawned->spr.pos);
|
||||
spawned->spr.hitag = actor->spr.hitag;
|
||||
spawned->temp_pos.Z = spawned->spr.pos.Z; // doesn't look to be used anywhere...
|
||||
|
||||
if (x < 64)
|
||||
{
|
||||
spawned->spr.scale.X = (x * (REPEAT_SCALE / 2));
|
||||
break;
|
||||
}
|
||||
x -= 64;
|
||||
|
||||
actor->spr.pos += actor->temp_angle.ToVector() * 64;
|
||||
updatesector(actor->spr.pos, &curSect, 128);
|
||||
|
||||
if (curSect == nullptr)
|
||||
break;
|
||||
|
||||
ChangeActorSect(actor, curSect);
|
||||
|
||||
// this is a hack to work around the laser line sprite's art tile offset
|
||||
ChangeActorSect(spawned, curSect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actor->temp_data[0]++;
|
||||
actor->spr.pos = actor->temp_pos;
|
||||
ChangeActorSect(actor, oldSect);
|
||||
actor->temp_data[3] = 0;
|
||||
if (hit && lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
actor->temp_data[2] = 13;
|
||||
S_PlayActorSound(LASERTRIP_ARMING, actor);
|
||||
}
|
||||
else actor->temp_data[2] = 0;
|
||||
}
|
||||
if (actor->temp_data[0] == 33)
|
||||
{
|
||||
actor->temp_data[1]++;
|
||||
|
||||
|
||||
actor->temp_pos.XY() = actor->spr.pos.XY();
|
||||
actor->spr.pos += actor->temp_angle.ToVector() * 2;
|
||||
actor->spr.pos.Z -= 3;
|
||||
SetActor(actor, actor->spr.pos);
|
||||
|
||||
x = hitasprite(actor, nullptr);
|
||||
|
||||
actor->spr.pos.XY() = actor->temp_pos.XY();
|
||||
actor->spr.pos.Z += 3;
|
||||
SetActor(actor, actor->spr.pos);
|
||||
|
||||
if (actor->ovel.X != x && lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
actor->temp_data[2] = 13;
|
||||
S_PlayActorSound(LASERTRIP_ARMING, actor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
@ -1192,11 +1035,6 @@ void movestandables_d(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
else if (picnum == TRIPBOMB)
|
||||
{
|
||||
movetripbomb(act);
|
||||
}
|
||||
|
||||
else if (picnum >= CRACK1 && picnum <= CRACK1 + 3)
|
||||
{
|
||||
movecrack(act);
|
||||
|
|
|
@ -599,14 +599,6 @@ void animatesprites_d(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi
|
|||
|
||||
switch (h->spr.picnum)
|
||||
{
|
||||
case LASERLINE:
|
||||
if (!OwnerAc) break;
|
||||
if (t->sectp->lotag == 2) t->pal = 8;
|
||||
t->pos.Z = OwnerAc->spr.pos.Z - 3;
|
||||
if (gs.lasermode == 2 && ps[screenpeek].heat_on == 0)
|
||||
t->scale.Y = (0);
|
||||
t->shade = -127;
|
||||
break;
|
||||
case EXPLOSION2:
|
||||
case EXPLOSION2BOT:
|
||||
case FREEZEBLAST:
|
||||
|
|
|
@ -859,7 +859,9 @@ static void shootlaser(DDukeActor* actor, int p, DVector3 pos, DAngle ang)
|
|||
+ MulScale(krand(), lLifetimeVar, 14)
|
||||
- lLifetimeVar;
|
||||
}
|
||||
bomb->spr.detail = lTripBombControl;
|
||||
}
|
||||
else bomb->spr.detail = TRIPBOMB_TRIPWIRE;
|
||||
|
||||
// this originally used the sprite index as tag to link the laser segments.
|
||||
// This value is never used again to reference an actor by index. Decouple this for robustness.
|
||||
|
|
|
@ -236,22 +236,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
|
|||
|
||||
break;
|
||||
|
||||
case LASERLINE:
|
||||
act->spr.scale = DVector2(0.5, 0.09375);
|
||||
|
||||
if (gs.lasermode == 1)
|
||||
act->spr.cstat = CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_TRANSLUCENT;
|
||||
else if (gs.lasermode == 0 || gs.lasermode == 2)
|
||||
act->spr.cstat = CSTAT_SPRITE_ALIGNMENT_WALL;
|
||||
else
|
||||
{
|
||||
act->spr.scale = DVector2(0, 0);
|
||||
}
|
||||
|
||||
if (actj) act->spr.angle = actj->temp_angle + DAngle90;
|
||||
ChangeActorStat(act, STAT_MISC);
|
||||
break;
|
||||
|
||||
case FORCESPHERE:
|
||||
if (!actj)
|
||||
{
|
||||
|
@ -320,33 +304,9 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>*
|
|||
ChangeActorStat(act, STAT_MISC);
|
||||
break;
|
||||
|
||||
case TRIPBOMB:
|
||||
if (act->spr.lotag > ud.player_skill)
|
||||
{
|
||||
act->spr.scale = DVector2(0, 0);
|
||||
ChangeActorStat(act, STAT_MISC);
|
||||
break;
|
||||
}
|
||||
|
||||
act->spr.scale = DVector2(0.0625, 0.078125);
|
||||
|
||||
act->SetOwner(act);
|
||||
ud.bomb_tag = (ud.bomb_tag + 1) & 32767;
|
||||
act->spr.hitag = ud.bomb_tag;
|
||||
|
||||
act->vel.X = 1;
|
||||
ssp(act, CLIPMASK0);
|
||||
act->temp_data[0] = 17;
|
||||
act->temp_data[2] = 0;
|
||||
act->temp_angle = act->spr.angle;
|
||||
[[fallthrough]];
|
||||
|
||||
case SPACEMARINE:
|
||||
if (act->spr.picnum == SPACEMARINE)
|
||||
{
|
||||
act->spr.extra = 20;
|
||||
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
|
||||
}
|
||||
act->spr.extra = 20;
|
||||
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
|
||||
ChangeActorStat(act, STAT_ZOMBIEACTOR);
|
||||
break;
|
||||
|
||||
|
|
|
@ -59,8 +59,8 @@ public:
|
|||
// Some SE's stored indices in temp_data. For purposes of clarity avoid that. These variables are meant to store these elements now
|
||||
walltype* temp_walls[2]; // SE20 + SE128
|
||||
sectortype* temp_sect, *actorstayput;
|
||||
DAngle temp_angle; // only used by TRIPBOMB
|
||||
DVector3 temp_pos, temp_pos2; // used by TRIPBOMB, SE_26 and FIREBALL.
|
||||
DAngle temp_angle;
|
||||
DVector3 temp_pos, temp_pos2;
|
||||
|
||||
TObjPtr<DDukeActor*> temp_actor, seek_actor;
|
||||
|
||||
|
@ -153,10 +153,8 @@ struct user_defs
|
|||
|
||||
int const_visibility;
|
||||
|
||||
int runkey_mode;
|
||||
|
||||
int shadows;
|
||||
int coords, levelstats, m_coop, coop;
|
||||
int coords, m_coop, coop;
|
||||
int wchoice[MAXPLAYERS][MAX_WEAPONS];
|
||||
|
||||
int respawn_monsters, respawn_items, respawn_inventory, recstat, monsters_off, brightness;
|
||||
|
|
|
@ -6,14 +6,15 @@ BEGIN_DUKE_NS
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Duke, GetViewPlayer)
|
||||
player_struct* duke_getviewplayer()
|
||||
{
|
||||
ACTION_RETURN_POINTER(&ps[screenpeek]);
|
||||
return &ps[screenpeek];
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Duke, MaxPlayerHealth)
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(_Duke, getviewplayer, duke_getviewplayer)
|
||||
{
|
||||
ACTION_RETURN_INT(gs.max_player_health);
|
||||
PARAM_PROLOGUE;
|
||||
ACTION_RETURN_POINTER(duke_getviewplayer());
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Duke, MaxAmmoAmount)
|
||||
|
@ -113,6 +114,9 @@ DEFINE_FIELD(DDukeActor, spritesetindex)
|
|||
DEFINE_FIELD(DDukeActor, temp_walls)
|
||||
DEFINE_FIELD(DDukeActor, temp_sect)
|
||||
DEFINE_FIELD(DDukeActor, actorstayput)
|
||||
DEFINE_FIELD(DDukeActor, temp_pos)
|
||||
DEFINE_FIELD(DDukeActor, temp_pos2)
|
||||
DEFINE_FIELD(DDukeActor, temp_angle)
|
||||
|
||||
static void setSpritesetImage(DDukeActor* self, unsigned int index)
|
||||
{
|
||||
|
@ -141,16 +145,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, getglobalz, getglobalz)
|
|||
return 0;
|
||||
}
|
||||
|
||||
player_struct* DukeActor_findplayer(DDukeActor* self)
|
||||
player_struct* DukeActor_findplayer(DDukeActor* self, double* dist)
|
||||
{
|
||||
double a;
|
||||
return &ps[findplayer(self, &a)];
|
||||
return &ps[findplayer(self, dist? dist : &a)];
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, findplayer, DukeActor_findplayer)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
ACTION_RETURN_POINTER(DukeActor_findplayer(self));
|
||||
double d;
|
||||
auto p = DukeActor_findplayer(self, &d);
|
||||
if (numret > 0) ret[0].SetPointer(p);
|
||||
if (numret > 1) ret[1].SetFloat(d);
|
||||
return min(numret, 2);
|
||||
}
|
||||
|
||||
int DukeActor_ifhitbyweapon(DDukeActor* self)
|
||||
|
@ -199,6 +207,11 @@ DDukeActor* DukeActor_Spawn(DDukeActor* origin, int intname)
|
|||
{
|
||||
picnum = TileFiles.tileForName("BLOODPOOL");
|
||||
}
|
||||
if (FName(ENamedName(intname)) == FName("DukeExplosion2"))
|
||||
{
|
||||
picnum = TileFiles.tileForName("EXPLOSION2");
|
||||
}
|
||||
|
||||
|
||||
if (picnum == -1)
|
||||
{
|
||||
|
@ -252,7 +265,60 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, makeitfall, makeitfall)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// temporary helpers.
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, RandomScrap, RANDOMSCRAP)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
RANDOMSCRAP(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DukeActor_hitradius(DDukeActor* actor, int r, int hp1, int hp2, int hp3, int hp4)
|
||||
{
|
||||
fi.hitradius(actor, r, hp1, hp2, hp3, hp4);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, hitradius, DukeActor_hitradius)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
PARAM_INT(r);
|
||||
PARAM_INT(h1);
|
||||
PARAM_INT(h2);
|
||||
PARAM_INT(h3);
|
||||
PARAM_INT(h4);
|
||||
DukeActor_hitradius(self, r, h1, h2, h3, h4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, hitasprite, hitasprite)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
DDukeActor* p;
|
||||
double d = hitasprite(self, &p);
|
||||
if (numret > 0) ret[0].SetFloat(d);
|
||||
if (numret > 1) ret[1].SetPointer(p);
|
||||
return min(numret, 2);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, ChangeSector, ChangeActorSect)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
PARAM_POINTER(sec, sectortype);
|
||||
PARAM_INT(tail);
|
||||
ChangeActorSect(self, sec, tail);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, ChangeStat, ChangeActorStat)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
PARAM_INT(stat);
|
||||
PARAM_INT(tail);
|
||||
ChangeActorStat(self, stat, tail);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// temporary helpers to hide the fact that these flags are not part of the actor yet.
|
||||
DEFINE_ACTION_FUNCTION(DDukeActor, actorflag1)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DDukeActor);
|
||||
|
@ -282,7 +348,6 @@ DEFINE_ACTION_FUNCTION(DDukeActor, attackerflag2)
|
|||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// DukePlayer
|
||||
|
@ -657,6 +722,30 @@ DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, playerheight);
|
|||
DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, displayflags);
|
||||
DEFINE_GLOBAL_UNSIZED(gs)
|
||||
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, god);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, cashman);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, eog);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, clipping);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, user_pals);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, from_bonus);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, last_level);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, secretlevel);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, const_visibility);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, coop);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, respawn_monsters);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, respawn_items);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, respawn_inventory);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, recstat);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, monsters_off);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, brightness);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, ffire);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, multimode);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, player_skill);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, marker);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, bomb_tag);
|
||||
DEFINE_FIELD_X(DukeUserDefs, user_defs, cameraactor);
|
||||
DEFINE_GLOBAL_UNSIZED(ud)
|
||||
|
||||
|
||||
// this is only a temporary helper until weaponsandammosprites can be migrated to real class types. We absolutely do not want any access to tile numbers in the scripts - even now.
|
||||
void tspritetype_setWeaponOrAmmoSprite(tspritetype* targ, unsigned z)
|
||||
|
|
|
@ -14,4 +14,6 @@ spawnclasses
|
|||
990 = DukeTire
|
||||
911 = DukeCactus
|
||||
939 = DukeCactusBroke
|
||||
2566 = DukeTripbombPlaced
|
||||
2567 = DukeLaserline
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ version "4.10"
|
|||
#include "zscript/games/duke/actors/flammables.zs"
|
||||
#include "zscript/games/duke/actors/scrap.zs"
|
||||
#include "zscript/games/duke/actors/cactus.zs"
|
||||
#include "zscript/games/duke/actors/tripbomb.zs"
|
||||
|
||||
#include "zscript/games/blood/bloodgame.zs"
|
||||
#include "zscript/games/blood/ui/menu.zs"
|
||||
|
|
|
@ -5,6 +5,8 @@ enum EClipMask
|
|||
CLIPMASK1 = (256 << 16) + 64
|
||||
};
|
||||
|
||||
const MAXPLAYERS = 8;
|
||||
|
||||
class CoreActor native
|
||||
{
|
||||
const REPEAT_SCALE = 1. / 64.;
|
||||
|
|
264
wadsrc/static/zscript/games/duke/actors/tripbomb.zs
Normal file
264
wadsrc/static/zscript/games/duke/actors/tripbomb.zs
Normal file
|
@ -0,0 +1,264 @@
|
|||
|
||||
class DukeTripBomb : DukeActor
|
||||
{
|
||||
enum EMode
|
||||
{
|
||||
// Control flags for WW2GI weapons.
|
||||
TRIPBOMB_TRIPWIRE = 1,
|
||||
TRIPBOMB_TIMER = 2
|
||||
};
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
pic "TRIPBOMB";
|
||||
// Note: The trip bomb has its health defined through CON! Value is 100. Con-based definitions will take precendence.
|
||||
health 100;
|
||||
}
|
||||
|
||||
override void Initialize()
|
||||
{
|
||||
self.scale = (0.0625, 0.078125);
|
||||
ud.bomb_tag = (ud.bomb_tag + 1) & 32767;
|
||||
self.hitag = ud.bomb_tag;
|
||||
self.detail = TRIPBOMB_TRIPWIRE;
|
||||
}
|
||||
|
||||
override void Tick()
|
||||
{
|
||||
int j;
|
||||
double x;
|
||||
|
||||
if (self.statnum != STAT_STANDABLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int lTripBombControl = self.detail;
|
||||
if (lTripBombControl & TRIPBOMB_TIMER)
|
||||
{
|
||||
// we're on a timer....
|
||||
if (self.extra >= 0)
|
||||
{
|
||||
self.extra--;
|
||||
if (self.extra == 0)
|
||||
{
|
||||
self.temp_data[2] = 16;
|
||||
self.PlayActorSound(DukeSnd.LASERTRIP_ARMING);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (self.temp_data[2] > 0)
|
||||
{
|
||||
self.temp_data[2]--;
|
||||
if (self.temp_data[2] == 8)
|
||||
{
|
||||
self.PlayActorSound(Dukesnd.LASERTRIP_EXPLODE);
|
||||
for (j = 0; j < 5; j++) self.RandomScrap();
|
||||
int ex = self.extra;
|
||||
self.hitradius(gs.tripbombblastradius, ex >> 2, ex >> 1, ex - (ex >> 2), ex);
|
||||
|
||||
let spawned = self.spawn("DukeExplosion2");
|
||||
if (spawned)
|
||||
{
|
||||
spawned.angle = self.angle;
|
||||
spawned.vel.X = 348 / 16.;
|
||||
spawned.DoMove(CLIPMASK0);
|
||||
}
|
||||
|
||||
DukeStatIterator it;
|
||||
for(let a1 = it.First(STAT_MISC); a1; a1 = it.Next())
|
||||
{
|
||||
if (a1 is "DukeLaserLine" && self.hitag == a1.hitag)
|
||||
a1.scale = (0, 0);
|
||||
}
|
||||
self.Destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
let ex = self.extra;
|
||||
self.extra = 1;
|
||||
let ang = self.angle;
|
||||
j = self.ifhitbyweapon();
|
||||
if (j >= 0)
|
||||
{
|
||||
self.temp_data[2] = 16;
|
||||
}
|
||||
self.extra = ex;
|
||||
self.angle = ang;
|
||||
}
|
||||
|
||||
if (self.temp_data[0] < 32)
|
||||
{
|
||||
DukePlayer p;
|
||||
double x;
|
||||
[p, x] = self.findplayer();
|
||||
if (x > 48) self.temp_data[0]++;
|
||||
else if (self.temp_data[0] > 16) self.temp_data[0]++;
|
||||
}
|
||||
if (self.temp_data[0] == 32)
|
||||
{
|
||||
let ang = self.angle;
|
||||
self.angle = self.temp_angle;
|
||||
|
||||
self.temp_pos = self.pos;
|
||||
self.pos += self.temp_angle.ToVector() * 2;
|
||||
self.pos.Z -= 3;
|
||||
|
||||
// Laser fix from EDuke32.
|
||||
let oldSect = self.sector;
|
||||
let curSect = self.sector;
|
||||
|
||||
curSect = Raze.updatesector(self.pos.XY, curSect, 128);
|
||||
self.ChangeSector(curSect);
|
||||
|
||||
DukeActor hit;
|
||||
[x, hit] = self.hitasprite();
|
||||
|
||||
self.temp_pos2.X = x;
|
||||
|
||||
self.angle = ang;
|
||||
|
||||
if (lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
// we're on a trip wire
|
||||
while (x > 0)
|
||||
{
|
||||
let spawned = self.spawn("DukeLaserLine");// LASERLINE);
|
||||
if (spawned)
|
||||
{
|
||||
spawned.SetPosition(spawned.pos);
|
||||
spawned.hitag = self.hitag;
|
||||
spawned.temp_pos.Z = spawned.pos.Z; // doesn't look to be used anywhere...
|
||||
|
||||
if (x < 64)
|
||||
{
|
||||
spawned.scale.X = (x * (REPEAT_SCALE / 2));
|
||||
break;
|
||||
}
|
||||
x -= 64;
|
||||
|
||||
self.pos += self.temp_angle.ToVector() * 64;
|
||||
cursect = Raze.updatesector(self.pos.XY, curSect, 128);
|
||||
|
||||
if (curSect == nullptr)
|
||||
break;
|
||||
|
||||
self.ChangeSector(curSect);
|
||||
|
||||
// this is a hack to work around the laser line sprite's art tile offset
|
||||
spawned.ChangeSector(curSect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.temp_data[0]++;
|
||||
self.pos = self.temp_pos;
|
||||
self.ChangeSector(oldSect);
|
||||
self.temp_data[3] = 0;
|
||||
if (hit && lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
self.temp_data[2] = 13;
|
||||
self.PlayActorSound(DukeSnd.LASERTRIP_ARMING);
|
||||
}
|
||||
else self.temp_data[2] = 0;
|
||||
}
|
||||
if (self.temp_data[0] == 33)
|
||||
{
|
||||
self.temp_data[1]++;
|
||||
|
||||
|
||||
self.temp_pos.XY = self.pos.XY;
|
||||
self.pos += self.temp_angle.ToVector() * 2;
|
||||
self.pos.Z -= 3;
|
||||
self.SetPosition(self.pos);
|
||||
|
||||
x = self.hitasprite();
|
||||
|
||||
self.pos.XY = self.temp_pos.XY;
|
||||
self.pos.Z += 3;
|
||||
self.SetPosition( self.pos);
|
||||
|
||||
if (self.temp_pos2.X != x && lTripBombControl & TRIPBOMB_TRIPWIRE)
|
||||
{
|
||||
self.temp_data[2] = 13;
|
||||
self.PlayActorSound(DukeSnd.LASERTRIP_ARMING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the map-spawned and player-spawned trip bombs are different so let's spawn two distinct types for them.
|
||||
class DukeTripBombPlaced : DukeTripBomb
|
||||
{
|
||||
override void Initialize()
|
||||
{
|
||||
if (self.lotag > ud.player_skill)
|
||||
{
|
||||
self.scale = (0, 0);
|
||||
self.ChangeStat(STAT_MISC);
|
||||
return;
|
||||
}
|
||||
Super.Initialize();
|
||||
|
||||
self.ownerActor = self;
|
||||
self.vel.X = 1;
|
||||
self.DoMove(CLIPMASK0);
|
||||
self.temp_data[0] = 17;
|
||||
self.temp_data[2] = 0;
|
||||
self.temp_angle = self.angle;
|
||||
self.ChangeStat(STAT_ZOMBIEACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class DukeLaserLine : DukeActor
|
||||
{
|
||||
default
|
||||
{
|
||||
statnum STAT_MISC;
|
||||
pic "LASERLINE";
|
||||
}
|
||||
|
||||
override void Initialize()
|
||||
{
|
||||
self.scale = (0.5, 0.09375);
|
||||
|
||||
if (gs.lasermode == 1)
|
||||
self.cstat = CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_TRANSLUCENT;
|
||||
else if (gs.lasermode == 0 || gs.lasermode == 2)
|
||||
self.cstat = CSTAT_SPRITE_ALIGNMENT_WALL;
|
||||
else
|
||||
{
|
||||
self.scale = (0, 0);
|
||||
}
|
||||
|
||||
let owner = self.ownerActor;
|
||||
if (owner) self.angle = owner.temp_angle + 90;
|
||||
self.ChangeStat(STAT_MISC);
|
||||
}
|
||||
|
||||
override bool animate(tspritetype t)
|
||||
{
|
||||
let OwnerAc = self.ownerActor;
|
||||
if (!OwnerAc) return true;
|
||||
if (t.sector.lotag == 2) t.pal = 8;
|
||||
t.pos.Z = OwnerAc.pos.Z - 3;
|
||||
if (gs.lasermode == 2 && Duke.GetViewPlayer().heat_on == 0)
|
||||
t.scale.Y = 0;
|
||||
t.shade = -127;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -40,6 +40,8 @@ class DukeActor : CoreActor native
|
|||
native sectortype temp_sect, actorstayput;
|
||||
|
||||
native DukeActor temp_actor, seek_actor;
|
||||
native Vector3 temp_pos, temp_pos2;
|
||||
native double temp_angle;
|
||||
|
||||
|
||||
flagdef Inventory: flags1, 0;
|
||||
|
@ -65,7 +67,7 @@ class DukeActor : CoreActor native
|
|||
flagdef NoInterpolate: flags1, 20;
|
||||
|
||||
native void getglobalz();
|
||||
native DukePlayer findplayer();
|
||||
native DukePlayer, double findplayer();
|
||||
native int ifhitbyweapon();
|
||||
native int domove(int clipmask);
|
||||
native void PlayActorSound(int snd);
|
||||
|
@ -82,6 +84,13 @@ class DukeActor : CoreActor native
|
|||
virtual void onUse(DukePlayer user) {}
|
||||
virtual bool animate(tspritetype tspr) { return false; }
|
||||
virtual void RunState() {} // this is the CON function.
|
||||
|
||||
native void RandomScrap();
|
||||
native void hitradius(int r, int hp1, int hp2, int hp3, int hp4);
|
||||
native double, DukeActor hitasprite();
|
||||
native void ChangeSector(sectortype s, bool forcetail = false);
|
||||
native void ChangeStat(int s, bool forcetail = false);
|
||||
|
||||
|
||||
// temporary flag accessors - need to be eliminated once we can have true actor flags
|
||||
native int actorflag1(int mask);
|
||||
|
@ -95,6 +104,7 @@ class DukeActor : CoreActor native
|
|||
extend struct _
|
||||
{
|
||||
native @DukeGameInfo gs;
|
||||
native @DukeUserDefs ud;
|
||||
native DukeLevel dlevel;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@ struct Duke native
|
|||
native static void StopSound(int num);
|
||||
native static bool CheckSoundPlaying(int num);
|
||||
native static DukePlayer GetViewPlayer();
|
||||
native static int MaxPlayerHealth();
|
||||
native static int MaxAmmoAmount(int weap);
|
||||
native static DukePlayer checkcursectnums(sectortype sect);
|
||||
|
||||
|
@ -120,7 +119,7 @@ struct Duke native
|
|||
}
|
||||
}
|
||||
|
||||
struct DukePlayer
|
||||
struct DukePlayer native
|
||||
{
|
||||
native Vector3 pos;
|
||||
|
||||
|
@ -1270,3 +1269,21 @@ struct DukeGameInfo native
|
|||
readonly native double playerheight;
|
||||
readonly native int displayflags;
|
||||
}
|
||||
|
||||
|
||||
struct DukeUserDefs native
|
||||
{
|
||||
native readonly uint8 god, cashman, eog;
|
||||
native readonly uint8 clipping;
|
||||
native readonly uint8 user_pals[MAXPLAYERS];
|
||||
native readonly int16 from_bonus;
|
||||
native readonly int16 last_level, secretlevel;
|
||||
native readonly int const_visibility;
|
||||
native readonly int coop;
|
||||
native readonly int respawn_monsters, respawn_items, respawn_inventory, recstat, monsters_off, brightness;
|
||||
native readonly int ffire, multimode;
|
||||
native readonly int player_skill, marker;
|
||||
|
||||
native int16 bomb_tag;
|
||||
native DukeActor cameraactor;
|
||||
}
|
||||
|
|
|
@ -148,10 +148,10 @@ class DukeStatusBar : DukeCommonStatusBar
|
|||
imgScale = baseScale / siz.Y;
|
||||
DrawTexture(img, (2, -1.5), DI_ITEM_LEFT_BOTTOM, scale:(imgScale, imgScale));
|
||||
|
||||
if (!althud_flashing || p.last_extra > (Duke.MaxPlayerHealth() >> 2) || (PlayClock & 32) || (p.IsFrozen() && p.last_extra < 2))
|
||||
if (!althud_flashing || p.last_extra > (gs.max_player_health >> 2) || (PlayClock & 32) || (p.IsFrozen() && p.last_extra < 2))
|
||||
{
|
||||
int s = -8;
|
||||
if (althud_flashing && p.last_extra > Duke.MaxPlayerHealth())
|
||||
if (althud_flashing && p.last_extra > gs.max_player_health)
|
||||
s += Raze.bsin(Raze.GetBuildTime() << 5) >> 10;
|
||||
int intens = clamp(255 - 6 * s, 0, 255);
|
||||
format = String.Format("%d", p.last_extra);
|
||||
|
|
|
@ -96,10 +96,10 @@ class RedneckStatusBar : DukeCommonStatusBar
|
|||
imgScale = baseScale / siz.Y;
|
||||
DrawTexture(img, (2, -2), DI_ITEM_LEFT_BOTTOM, scale:(imgScale, imgScale));
|
||||
|
||||
if (!althud_flashing || p.last_extra > (Duke.MaxPlayerHealth() >> 2) || (PlayClock & 32) || (p.IsFrozen() && p.last_extra < 2))
|
||||
if (!althud_flashing || p.last_extra > (gs.max_player_health >> 2) || (PlayClock & 32) || (p.IsFrozen() && p.last_extra < 2))
|
||||
{
|
||||
int s = -8;
|
||||
if (althud_flashing && p.last_extra > Duke.MaxPlayerHealth())
|
||||
if (althud_flashing && p.last_extra > gs.max_player_health)
|
||||
s += Raze.bsin(Raze.GetBuildTime() << 5) >> 10;
|
||||
int intens = clamp(255 - 6 * s, 0, 255);
|
||||
format = String.Format("%d", p.last_extra);
|
||||
|
|
|
@ -279,6 +279,7 @@ struct walltype native
|
|||
|
||||
struct tspritetype native
|
||||
{
|
||||
native Vector3 pos;
|
||||
native sectortype sector;
|
||||
native int16 cstat;
|
||||
//native int16 picnum;
|
||||
|
|
|
@ -149,6 +149,8 @@ struct Raze
|
|||
native static int GetBuildTime();
|
||||
native static Font PickBigFont(String cmptext = "");
|
||||
native static Font PickSmallFont(String cmptext = "");
|
||||
|
||||
native static sectortype updatesector(Vector2 pos, sectortype lastsect, double maxdist = 96);
|
||||
|
||||
// game check shortcuts
|
||||
|
||||
|
|
Loading…
Reference in a new issue