diff --git a/source/core/actorinfo.h b/source/core/actorinfo.h index 3c1cc67d5..1e8e2bc1b 100644 --- a/source/core/actorinfo.h +++ b/source/core/actorinfo.h @@ -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. diff --git a/source/core/thingdef_properties.cpp b/source/core/thingdef_properties.cpp index 3f96d3caf..f6d6d44a9 100644 --- a/source/core/thingdef_properties.cpp +++ b/source/core/thingdef_properties.cpp @@ -500,3 +500,12 @@ DEFINE_PROPERTY(spriteset, Sssssssssssssssssssssssssssssss, CoreActor) } } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(health, I, CoreActor) +{ + PROP_INT_PARM(i, 0); + bag.Info->ActorInfo()->Health = i; +} + diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index dcef7eadf..4e0ff8081 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -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; } - - diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index 03b4b5aab..923055ce6 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -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); diff --git a/source/games/duke/src/animatesprites_d.cpp b/source/games/duke/src/animatesprites_d.cpp index 68fae5f14..5b770af59 100644 --- a/source/games/duke/src/animatesprites_d.cpp +++ b/source/games/duke/src/animatesprites_d.cpp @@ -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: diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index efa32e944..37ac10a0a 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -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. diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 48248a164..fba08314f 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -236,22 +236,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* 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* 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; diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 217cec57c..2c5e459ce 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -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 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; diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index de4a0b95b..227d04615 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -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) diff --git a/wadsrc/static/filter/duke/engine/engine.def b/wadsrc/static/filter/duke/engine/engine.def index dd8208ce2..235fd78c4 100644 --- a/wadsrc/static/filter/duke/engine/engine.def +++ b/wadsrc/static/filter/duke/engine/engine.def @@ -14,4 +14,6 @@ spawnclasses 990 = DukeTire 911 = DukeCactus 939 = DukeCactusBroke + 2566 = DukeTripbombPlaced + 2567 = DukeLaserline } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 5ce00e443..32c3d9105 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -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" diff --git a/wadsrc/static/zscript/coreactor.zs b/wadsrc/static/zscript/coreactor.zs index 7d94a4191..f49638ca3 100644 --- a/wadsrc/static/zscript/coreactor.zs +++ b/wadsrc/static/zscript/coreactor.zs @@ -5,6 +5,8 @@ enum EClipMask CLIPMASK1 = (256 << 16) + 64 }; +const MAXPLAYERS = 8; + class CoreActor native { const REPEAT_SCALE = 1. / 64.; diff --git a/wadsrc/static/zscript/games/duke/actors/tripbomb.zs b/wadsrc/static/zscript/games/duke/actors/tripbomb.zs new file mode 100644 index 000000000..0276f6d8d --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/tripbomb.zs @@ -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; + } + + + +} + diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 7ef03823a..56c9dcd98 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -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; } diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index eee42a1c2..629b8e5c0 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -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; +} diff --git a/wadsrc/static/zscript/games/duke/ui/sbar_d.zs b/wadsrc/static/zscript/games/duke/ui/sbar_d.zs index 1f374c7e6..8ae7a054f 100644 --- a/wadsrc/static/zscript/games/duke/ui/sbar_d.zs +++ b/wadsrc/static/zscript/games/duke/ui/sbar_d.zs @@ -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); diff --git a/wadsrc/static/zscript/games/duke/ui/sbar_r.zs b/wadsrc/static/zscript/games/duke/ui/sbar_r.zs index 144b1efcb..ea6b3936b 100644 --- a/wadsrc/static/zscript/games/duke/ui/sbar_r.zs +++ b/wadsrc/static/zscript/games/duke/ui/sbar_r.zs @@ -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); diff --git a/wadsrc/static/zscript/maptypes.zs b/wadsrc/static/zscript/maptypes.zs index fe3c27722..6fdb4a436 100644 --- a/wadsrc/static/zscript/maptypes.zs +++ b/wadsrc/static/zscript/maptypes.zs @@ -279,6 +279,7 @@ struct walltype native struct tspritetype native { + native Vector3 pos; native sectortype sector; native int16 cstat; //native int16 picnum; diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index 01591c4bc..708d5cd27 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -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