- scriptified the trip bombs.

This commit is contained in:
Christoph Oelckers 2022-11-17 18:38:25 +01:00
parent 133cb3a02e
commit 8ce358fc24
19 changed files with 438 additions and 235 deletions

View file

@ -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.

View file

@ -500,3 +500,12 @@ DEFINE_PROPERTY(spriteset, Sssssssssssssssssssssssssssssss, CoreActor)
}
}
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(health, I, CoreActor)
{
PROP_INT_PARM(i, 0);
bag.Info->ActorInfo()->Health = i;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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:

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -14,4 +14,6 @@ spawnclasses
990 = DukeTire
911 = DukeCactus
939 = DukeCactusBroke
2566 = DukeTripbombPlaced
2567 = DukeLaserline
}

View file

@ -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"

View file

@ -5,6 +5,8 @@ enum EClipMask
CLIPMASK1 = (256 << 16) + 64
};
const MAXPLAYERS = 8;
class CoreActor native
{
const REPEAT_SCALE = 1. / 64.;

View 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;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -279,6 +279,7 @@ struct walltype native
struct tspritetype native
{
native Vector3 pos;
native sectortype sector;
native int16 cstat;
//native int16 picnum;

View file

@ -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