diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index 9c3c138c8..beeb9ccf3 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -91,7 +91,7 @@ void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane) pe.a = 230; sky->fadecolor = pe; - sky->shade = clamp(plane == plane_ceiling ? sector->ceilingshade : sector->floorshade, 0, numshades - 1); + sky->shade = 0;// clamp(plane == plane_ceiling ? sector->ceilingshade : sector->floorshade, 0, numshades - 1); sky->texture = skytex; } diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index 928312081..4754510ac 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -822,6 +822,7 @@ DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Yaw, angle) DEFINE_FIELD_NAMED(DCoreActor, spr.Angles.Pitch, pitch) DEFINE_FIELD(DCoreActor, vel) DEFINE_FIELD(DCoreActor, viewzoffset) +DEFINE_FIELD(DCoreActor, oviewzoffset) DEFINE_FIELD(DCoreActor, opos) void coreactor_setpos(DCoreActor* self, double x, double y, double z, int relink) diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp index 0fd8d8f73..7c23b8b3d 100644 --- a/source/games/blood/src/aicerber.cpp +++ b/source/games/blood/src/aicerber.cpp @@ -96,7 +96,7 @@ void cerberusBurnSeqCallback(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; @@ -161,7 +161,7 @@ void cerberusBurnSeqCallback2(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp index c91540c01..af45755f8 100644 --- a/source/games/blood/src/aigarg.cpp +++ b/source/games/blood/src/aigarg.cpp @@ -121,7 +121,7 @@ void BlastSSeqCallback(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp index dbfbc3e26..326be2be8 100644 --- a/source/games/blood/src/aighost.cpp +++ b/source/games/blood/src/aighost.cpp @@ -108,7 +108,7 @@ void ghostBlastSeqCallback(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp index ad1b3290a..8cf17729e 100644 --- a/source/games/blood/src/aitchern.cpp +++ b/source/games/blood/src/aitchern.cpp @@ -79,7 +79,7 @@ void tchernobogBurnSeqCallback(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; @@ -135,7 +135,7 @@ void tchernobogBurnSeqCallback2(int, DBloodActor* actor) if (nDist == 0 || nDist > 0x280) continue; - pos += actor2->vel * nDist * (65536. / 0x1aaaaa); + pos2 += actor->vel * nDist * (65536. / 0x1aaaaa); DVector3 tvec = pos; tvec.XY() += actor->spr.Angles.Yaw.ToVector() * nDist; diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 77147f2b9..32c303d3e 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -800,7 +800,6 @@ void nnExtInitModernStuff(TArray& actors) { if (iactor->xspr.busyTime <= 0 || iactor->xspr.isTriggered) continue; - int count = 0; TRCONDITION* pCond = &gConditions[gConditions.Reserve(1)]; for (auto iactor2 : actors) @@ -818,18 +817,18 @@ void nnExtInitModernStuff(TArray& actors) if (iactor2->spr.type == kModernCondition || iactor2->spr.type == kModernConditionFalse) condError(iactor, "Tracking condition always must be first in condition sequence!"); - pCond->objects.Reserve(2); - pCond->objects[count].obj = EventObject(iactor2); - pCond->objects[count++].cmd = (uint8_t)iactor2->xspr.command; + pCond->objects.Reserve(1); + pCond->objects.Last().obj = EventObject(iactor2); + pCond->objects.Last().cmd = (uint8_t)iactor2->xspr.command; } for (auto& sect : sector) { if (!sect.hasX() || sect.xs().txID != iactor->xspr.rxID) continue; - pCond->objects.Reserve(2); - pCond->objects[count].obj = EventObject(§); - pCond->objects[count++].cmd = sect.xs().command; + pCond->objects.Reserve(1); + pCond->objects.Last().obj = EventObject(§); + pCond->objects.Last().cmd = sect.xs().command; } for (auto& wal : wall) @@ -843,12 +842,12 @@ void nnExtInitModernStuff(TArray& actors) continue; } - pCond->objects.Reserve(2); - pCond->objects[count].obj = EventObject(&wal); - pCond->objects[count++].cmd = wal.xw().command; + pCond->objects.Reserve(1); + pCond->objects.Last().obj = EventObject(&wal); + pCond->objects.Last().cmd = wal.xw().command; } - if (iactor->xspr.data1 > kCondGameMax && count == 0) + if (iactor->xspr.data1 > kCondGameMax && pCond->objects.Size() == 0) Printf(PRINT_HIGH, "No objects to track found for condition #%d, RXID: %d!", iactor->GetIndex(), iactor->xspr.rxID); pCond->actor = iactor; diff --git a/source/games/blood/src/nnexts.h b/source/games/blood/src/nnexts.h index 18bd1b578..ae551a526 100644 --- a/source/games/blood/src/nnexts.h +++ b/source/games/blood/src/nnexts.h @@ -239,12 +239,12 @@ struct TRPLAYERCTRL { // this one for controlling the player using triggers (mov }; struct OBJECTS_TO_TRACK { - uint8_t cmd; - EventObject obj; + uint8_t cmd = 0; + EventObject obj = EventObject(nullptr); }; struct TRCONDITION { - DBloodActor* actor; + DBloodActor* actor = nullptr; TArray objects; }; diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index 9a4a46b18..d3ed130a8 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -1452,7 +1452,7 @@ int ActionScan(PLAYER* pPlayer, HitInfo* out) int nMass = getDudeInfo(hitactor->spr.type)->mass; if (nMass) { - hitactor->spr.pos += pos * (FixedToFloat<8>(0xccccc) / nMass); + hitactor->vel += pos * (FixedToFloat<10>(0xccccc) / nMass); } if (hitactor->xspr.Push && !hitactor->xspr.state && !hitactor->xspr.isTriggered) trTriggerSprite(hitactor, kCmdSpritePush); diff --git a/source/games/duke/src/actors.cpp b/source/games/duke/src/actors.cpp index 4bf59a4d1..019be65ca 100644 --- a/source/games/duke/src/actors.cpp +++ b/source/games/duke/src/actors.cpp @@ -577,9 +577,11 @@ void tickstat(int stat, bool deleteinvalid) if (actorflag(act, SFLAG2_DIENOW) || act->sector() == nullptr || (deleteinvalid && act->spr.scale.X == 0)) { act->Destroy(); - continue; } - CallTick(act); + else if (stat != STAT_ACTOR || !badguy(act) || !monsterCheatCheck(act)) + { + CallTick(act); + } } } @@ -2964,6 +2966,8 @@ void getglobalz(DDukeActor* actor) void makeitfall(DDukeActor* actor) { + if (actorflag(actor, SFLAG3_NOGRAVITY)) return; + double grav; if( floorspace(actor->sector()) ) @@ -2993,7 +2997,7 @@ void makeitfall(DDukeActor* actor) if( actor->spr.pos.Z < actor->floorz - FOURSLEIGHT_F) { - if( actor->sector()->lotag == 2 && actor->vel.Z > 3122/256.) + if( actor->sector()->lotag == ST_2_UNDERWATER && actor->vel.Z > 3122/256.) actor->vel.Z = 3144 / 256.; if (actor->vel.Z < 24) actor->vel.Z += grav; diff --git a/source/games/duke/src/actors_d.cpp b/source/games/duke/src/actors_d.cpp index f4d0343f5..ef4e43f5b 100644 --- a/source/games/duke/src/actors_d.cpp +++ b/source/games/duke/src/actors_d.cpp @@ -991,201 +991,6 @@ void movetransports_d(void) // //--------------------------------------------------------------------------- -static void flamethrowerflame(DDukeActor *actor) -{ - auto sectp = actor->sector(); - double xx; - int p = findplayer(actor, &xx); - execute(actor, p, xx); - if (actor->ObjectFlags & OF_EuthanizeMe) return; // killed by script. - actor->temp_data[0]++; - if (sectp->lotag == 2) - { - spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127; - actor->Destroy(); - return; - } - - auto dapos = actor->spr.pos; - - getglobalz(actor); - - int ds = actor->temp_data[0] / 6; - if (actor->spr.scale.X < 0.1250) - { - actor->spr.scale.X += (ds * REPEAT_SCALE); - actor->spr.scale.Y = (actor->spr.scale.X); - } - actor->clipdist += ds * 0.25; - if (actor->temp_data[0] <= 2) - actor->temp_data[3] = krand() % 10; - if (actor->temp_data[0] > 30) - { - spawn(actor, DTILE_EXPLOSION2)->spr.shade = 127; - actor->Destroy(); - return; - } - - Collision coll; - movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK1, coll); - - if (!actor->insector()) - { - actor->Destroy(); - return; - } - - if (coll.type != kHitSprite) - { - if (actor->spr.pos.Z < actor->ceilingz) - { - coll.setSector(actor->sector()); - actor->vel.Z -= 1/256.; - } - else if ((actor->spr.pos.Z > actor->floorz && actor->sector()->lotag != 1) - || (actor->spr.pos.Z > actor->floorz + 16 && actor->sector()->lotag == 1)) - { - coll.setSector(actor->sector()); - if (actor->sector()->lotag != 1) - actor->vel.Z += 1/256.; - } - } - - if (coll.type != 0) { - actor->vel.XY().Zero(); - actor->vel.Z = 0; - if (coll.type == kHitSprite) - { - fi.checkhitsprite(coll.actor(), actor); - if (coll.actor()->isPlayer()) - S_PlayActorSound(PISTOL_BODYHIT, coll.actor()); - } - else if (coll.type == kHitWall) - { - SetActor(actor, dapos); - checkhitwall(actor, coll.hitWall, actor->spr.pos); - } - else if (coll.type == kHitSector) - { - SetActor(actor, dapos); - if (actor->vel.Z < 0) - checkhitceiling(actor->sector()); - } - - if (actor->spr.scale.X >= 0.15625) - { - int x = actor->spr.extra; - fi.hitradius(actor, gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); - } - else - { - int x = actor->spr.extra + (global_random & 3); - fi.hitradius(actor, (gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); - } - } -} - - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void moveactors_d(void) -{ - DukeStatIterator it(STAT_ACTOR); - while (auto act = it.Next()) - { - if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW)) - { - act->Destroy(); - } - else if (monsterCheatCheck(act) && badguy(act)) - { - continue; - } - else if (isWorldTour() && act->spr.picnum == DTILE_FLAMETHROWERFLAME) - { - flamethrowerflame(act); - } - else - { - CallTick(act); - } - } - -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void fireflyflyingeffect(DDukeActor *actor) -{ - double xx; - int p = findplayer(actor, &xx); - execute(actor, p, xx); - if (actor->ObjectFlags & OF_EuthanizeMe) return; // killed by script. - - auto Owner = actor->GetOwner(); - if (!Owner || Owner->spr.picnum != DTILE_FIREFLY) - { - actor->Destroy(); - return; - } - - if (Owner->spr.scale.X >= 0.375 || Owner->spr.pal == 1) - actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE; - else - actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE; - - auto dvec = Owner->spr.pos.XY() - ps[p].GetActor()->spr.pos.XY(); - double dist = dvec.Length(); - - if (dist != 0.0) dvec /= dist; - actor->spr.pos = Owner->spr.pos + DVector3(dvec.X * -0.625, dvec.Y * -0.625, 8); - - if (Owner->spr.extra <= 0) - { - actor->Destroy(); - } - -} -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -void moveexplosions_d(void) // STATNUM 5 -{ - DukeStatIterator it(STAT_MISC); - while (auto act = it.Next()) - { - if (act->spr.scale.X == 0 || act->spr.sectp == nullptr || actorflag(act, SFLAG2_DIENOW)) - { - act->Destroy(); - } - else if (isWorldTour() && act->spr.picnum == DTILE_FIREFLYFLYINGEFFECT) - { - fireflyflyingeffect(act); - } - else - { - CallTick(act); - } - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - void handle_se06_d(DDukeActor* actor) { auto sc = actor->sector(); @@ -1741,11 +1546,11 @@ void think_d(void) tickstat(STAT_PROJECTILE); //ST 4 moveplayers(); //ST 10 movefallers_d(); //ST 12 - moveexplosions_d(); //ST 5 + tickstat(STAT_MISC, true); //ST 5 actortime.Reset(); actortime.Clock(); - moveactors_d(); //ST 1 + tickstat(STAT_ACTOR); //ST 1 actortime.Unclock(); moveeffectors_d(); //ST 3 diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index a30b368e2..76104575c 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -1018,10 +1018,6 @@ static void rrra_specialstats() void moveactors_r(void) { - double xx; - int p; - Collision coll; - dojaildoor(); moveminecart(); @@ -1033,46 +1029,7 @@ void moveactors_r(void) if (ud.chickenplant) tickstat(STAT_CHICKENPLANT); tickstat(STAT_BOWLING); tickstat(STAT_TELEPORT); - - DukeStatIterator it(STAT_ACTOR); - while (auto act = it.Next()) - { - if( act->spr.scale.X == 0 || !act->insector() || actorflag(act, SFLAG2_DIENOW)) - { - act->Destroy(); - continue; - } - if (monsterCheatCheck(act) && badguy(act)) - { - continue; - } - - auto sectp = act->sector(); - - if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) - { - CallTick(act); - continue; - } - else switch(act->spr.picnum) - { - case RTILE_POWDERKEG: - if (!isRRRA() || (sectp->lotag != ST_1_ABOVE_WATER && sectp->lotag != ST_160_FLOOR_TELEPORT)) - if (act->vel.X != 0) - { - movesprite_ex(act, DVector3(act->spr.Angles.Yaw.ToVector()* act->vel.X, act->vel.Z), CLIPMASK0, coll); - act->vel.X -= 1. / 16.; - } - break; - } - - - - p = findplayer(act, &xx); - - execute(act,p,xx); - } - + tickstat(STAT_ACTOR); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index 70ce18757..f65fcc7f7 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -126,8 +126,6 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi if (h->spr.extra > 0) t->pos.Z += 6; break; - case RTILE_POWDERKEG: - continue; case RTILE_BURNING: if (OwnerAc && OwnerAc->spr.statnum == STAT_PLAYER) { diff --git a/source/games/duke/src/constants.h b/source/games/duke/src/constants.h index 3b94d2bb1..3cf06df77 100644 --- a/source/games/duke/src/constants.h +++ b/source/games/duke/src/constants.h @@ -404,6 +404,7 @@ enum sflags3_t SFLAG3_BROWNBLOOD = 0x00000004, SFLAG3_LIGHTDAMAGE = 0x00000008, SFLAG3_FORCERUNCON = 0x00000010, // by default only STAT_ACTOR runs CON - this enables it for other statnums as well, provided they run Tick() + SFLAG3_NOGRAVITY = 0x00000020, // disables makeitfall. }; diff --git a/source/games/duke/src/flags_d.cpp b/source/games/duke/src/flags_d.cpp index 9e950d42f..611866d49 100644 --- a/source/games/duke/src/flags_d.cpp +++ b/source/games/duke/src/flags_d.cpp @@ -40,6 +40,7 @@ BEGIN_DUKE_NS void initactorflags_d() { + setflag(SFLAG3_NOGRAVITY, { DTILE_RECON }); // not ported!!! gs.actorinfo[DTILE_COMMANDER].gutsoffset = -24; diff --git a/source/games/duke/src/flags_r.cpp b/source/games/duke/src/flags_r.cpp index 650f116d5..c5fcecad2 100644 --- a/source/games/duke/src/flags_r.cpp +++ b/source/games/duke/src/flags_r.cpp @@ -232,6 +232,7 @@ void initactorflags_r() RTILE_SHITBALL, RTILE_RPG, RTILE_RECON, + RTILE_POWDERKEG }); // Animals were not supposed to have this, but due to a coding bug the logic was unconditional for everything in the game. for (auto& ainf : gs.actorinfo) diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 5dbf8bb5d..f478ef63a 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -175,7 +175,7 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* void addspritetodelete(int spnum=0); void checkavailinven(player_struct* p); bool initspriteforspawn(DDukeActor* spn); -bool spawninitdefault(DDukeActor* actj, DDukeActor* act); +bool commonEnemySetup(DDukeActor* self, DDukeActor* owner); void spawntransporter(DDukeActor* actj, DDukeActor* acti, bool beam); int spawnbloodpoolpart1(DDukeActor* acti); void initshell(DDukeActor* actj, DDukeActor* acti, bool isshell); diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 88fc77bce..c9921713b 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -142,91 +142,6 @@ static void shootfireball(DDukeActor *actor, int p, DVector3 pos, DAngle ang) // //--------------------------------------------------------------------------- -static void shootflamethrowerflame(DDukeActor* actor, int p, DVector3 spos, DAngle sang) -{ - double vel, zvel = 0; - - if (actor->spr.extra >= 0) - actor->spr.shade = -96; - vel = 25; - - DDukeActor* spawned = nullptr; - if (p < 0) - { - double x; - int j = findplayer(actor, &x); - sang = (ps[j].GetActor()->opos.XY() - spos.XY()).Angle(); - - if (actor->spr.picnum == DTILE_BOSS5) - { - vel = 33; - spos.Z += 24; - } - else if (actor->spr.picnum == DTILE_BOSS3) - spos.Z -= 32; - - double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length(); - if (dist != 0) - zvel = (((ps[j].GetActor()->getPrevOffsetZ() - spos.Z) * vel) / dist); - - if (badguy(actor) && (actor->spr.hitag & face_player_smart) != 0) - sang = actor->spr.Angles.Yaw + mapangle((krand() & 31) - 16); - - if (actor->sector()->lotag == 2 && (krand() % 5) == 0) - spawned = spawn(actor, DTILE_WATERBUBBLE); - } - else - { - setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5); - - // WTF??? - DAngle myang = DAngle90 - (DAngle180 - abs(abs((spos.XY() - ps[p].GetActor()->spr.pos.XY()).Angle() - sang) - DAngle180)); - if (ps[p].GetActor()->vel.X != 0) - vel = ((myang / DAngle90) * ps[p].GetActor()->vel.X) + 25; - if (actor->sector()->lotag == 2 && (krand() % 5) == 0) - spawned = spawn(actor, DTILE_WATERBUBBLE); - } - - if (spawned == nullptr) - { - spawned = spawn(actor, DTILE_FLAMETHROWERFLAME); - if (!spawned) return; - spawned->vel.X = vel; - spawned->vel.Z = zvel; - } - - - DVector3 offset; - offset.X = (sang + DAngle::fromBuild(118)).Cos() * (1024 / 448.); // Yes, these angles are really different! - offset.Y = (sang + DAngle::fromBuild(112)).Sin() * (1024 / 448.); - offset.Z = -1; - - spawned->spr.pos = spos + offset; - spawned->spr.pos.Z--; - spawned->setsector(actor->sector()); - spawned->spr.cstat = CSTAT_SPRITE_YCENTER; - spawned->spr.Angles.Yaw = sang; - spawned->spr.scale = DVector2(0.03125, 0.03125); - spawned->clipdist = 10; - spawned->spr.yint = p; - spawned->SetOwner(actor); - - if (p == -1) - { - if (actor->spr.picnum == DTILE_BOSS5) - { - spawned->spr.pos += sang.ToVector() * (128. / 7); - spawned->spr.scale = DVector2(0.15625, 0.15625); - } - } -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - static void shootknee(DDukeActor* actor, int p, DVector3 pos, DAngle ang) { auto sectp = actor->sector(); @@ -1105,10 +1020,6 @@ void shoot_d(DDukeActor* actor, int atwith, PClass *cls) shootfireball(actor, p, spos, sang); return; - case DTILE_FLAMETHROWERFLAME: - shootflamethrowerflame(actor, p, spos, sang); - return; - case DTILE_FIREFLY: // DTILE_BOSS5 shot { auto k = spawn(actor, atwith); diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 78908912e..ae740a06f 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -845,17 +845,6 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls) shootweapon(actor, p, spos, sang, atwith); return; - case RTILE_POWDERKEG: - { - auto j = spawn(actor, atwith); - if (j) - { - j->vel.X = 2; - j->spr.Angles.Yaw = actor->spr.Angles.Yaw; - j->spr.pos.Z -= 5; - } - break; - } case RTILE_OWHIP: case RTILE_UWHIP: shootwhip(actor, p, spos, sang, atwith); diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index 2903f4343..863257450 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -298,63 +298,48 @@ DDukeActor* spawn(DDukeActor* actj, PClassActor * cls) // //--------------------------------------------------------------------------- -bool spawninitdefault(DDukeActor* actj, DDukeActor *act) +bool commonEnemySetup(DDukeActor* self, DDukeActor* owner) { - if (gs.actorinfo[act->spr.picnum].scriptaddress) + if (!self->mapSpawned) self->spr.lotag = 0; + + // Init the size. This is different for internal and user enemies. + if (actorflag(self, SFLAG_INTERNAL_BADGUY)) { - if (actj == nullptr && act->spr.lotag > ud.player_skill) - { - // make it go away... - act->spr.scale = DVector2(0, 0); - ChangeActorStat(act, STAT_MISC); - return false; - } - - // Init the size - if (act->spr.scale.X == 0 || act->spr.scale.Y == 0) - act->spr.scale = DVector2(REPEAT_SCALE, REPEAT_SCALE); - - if (actorflag(act, SFLAG_BADGUY)) - { - if (ud.monsters_off == 1) - { - act->spr.scale = DVector2(0, 0); - ChangeActorStat(act, STAT_MISC); - return false; - } - - makeitfall(act); - - if (actorflag(act, SFLAG_BADGUYSTAYPUT)) - act->actorstayput = act->sector(); - - if (!isRR() || actorflag(act, SFLAG_KILLCOUNT)) // Duke is just like Doom - Bad guys always count as kill. - ps[myconnectindex].max_actors_killed++; - - act->clipdist = 20; - if (actj) - { - if (isrespawncontroller(actj)) - act->tempval = act->spr.pal = actj->spr.pal; - ChangeActorStat(act, STAT_ACTOR); - } - else ChangeActorStat(act, STAT_ZOMBIEACTOR); - } - else - { - act->clipdist = 10; - act->SetOwner(act); - ChangeActorStat(act, STAT_ACTOR); - } - - act->timetosleep = 0; - - if (actj) - act->spr.Angles.Yaw = actj->spr.Angles.Yaw; + self->spr.scale = DVector2(0.625, 0.625); + } + else if (self->spr.scale.X == 0 || self->spr.scale.Y == 0) + { + self->spr.scale = DVector2(REPEAT_SCALE, REPEAT_SCALE); + } + + if ((self->spr.lotag > ud.player_skill) || ud.monsters_off == 1) + { + self->spr.scale.Zero(); + ChangeActorStat(self, STAT_MISC); + return false; + } + else + { + makeitfall(self); + + self->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; + + if (!isRR() && actorflag(self, SFLAG_KILLCOUNT)) + ps[myconnectindex].max_actors_killed++; + + self->timetosleep = 0; + if (!self->mapSpawned) + { + CallPlayFTASound(self); + ChangeActorStat(self, STAT_ACTOR); + if (owner && !actorflag(self, SFLAG_INTERNAL_BADGUY)) self->spr.Angles.Yaw = owner->spr.Angles.Yaw; + } + else ChangeActorStat(self, STAT_ZOMBIEACTOR); + return true; } - return true; } + //--------------------------------------------------------------------------- // // diff --git a/source/games/duke/src/spawn_d.cpp b/source/games/duke/src/spawn_d.cpp index 034c9138c..8a0ce7c5a 100644 --- a/source/games/duke/src/spawn_d.cpp +++ b/source/games/duke/src/spawn_d.cpp @@ -59,7 +59,7 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { - if (spawninitdefault(actj, act)) + if (!badguy(act) || commonEnemySetup(act, actj)) CallInitialize(act); return act; } @@ -123,11 +123,6 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* ChangeActorStat(act, STAT_ZOMBIEACTOR); } return act; - case DTILE_FIREFLYFLYINGEFFECT: - act->SetOwner(actj); - ChangeActorStat(act, STAT_MISC); - act->spr.scale = DVector2(0.25, 0.25); - return act; case DTILE_LAVAPOOLBUBBLE: if (actj->spr.scale.X < 0.46875) return act; @@ -154,7 +149,7 @@ DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* switch (act->spr.picnum) { default: - spawninitdefault(actj, act); + CallInitialize(act); break; case FOF: act->spr.scale = DVector2(0, 0); diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index 78a693f52..7fd943fd1 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -51,7 +51,7 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { - if (spawninitdefault(actj, act)) + if (!badguy(act) || commonEnemySetup(act, actj)) CallInitialize(act); return act; } @@ -61,7 +61,7 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* { default: default_case: - spawninitdefault(actj, act); + CallInitialize(act); break; case RTILE_RRTILE7936: if (!isRRRA()) goto default_case; diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index 2e1c7cb4e..64800e332 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -212,6 +212,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, StopCommentary, StopCommentary) return 0; } +int getPlayerIndex(player_struct* p) +{ + if (!p) return -1; + return int(p - ps); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Duke, getPlayerIndex, getPlayerIndex) +{ + PARAM_PROLOGUE; + PARAM_POINTER(p, player_struct); + ACTION_RETURN_INT(getPlayerIndex(p)); + return 0; +} + DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL(camsprite) @@ -609,6 +623,17 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, badguy, badguy) ACTION_RETURN_INT(badguy(self)); } +int duke_scripted(DDukeActor* act) +{ + return gs.actorinfo[act->spr.picnum].scriptaddress > 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, scripted, duke_scripted) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + ACTION_RETURN_INT(duke_scripted(self)); +} + int duke_isplayer(DDukeActor* act) { return act->isPlayer(); diff --git a/source/games/exhumed/src/view.cpp b/source/games/exhumed/src/view.cpp index f85b859b9..7ce9fcc10 100644 --- a/source/games/exhumed/src/view.cpp +++ b/source/games/exhumed/src/view.cpp @@ -110,7 +110,7 @@ static void analyzesprites(tspriteArray& tsprites, const DVector3& view, double pTSprite->pos.Z -= nTileY; } - if (pTSprite->pal == 4 && pTSprite->shade >= numshades) pTSprite->shade = numshades - 1; + if (pTSprite->pal == 4 && pTSprite->shade >= numshades && !hw_int_useindexedcolortextures) pTSprite->shade = numshades - 1; if (pActor->spr.statnum > 0) { diff --git a/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses b/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses index d0cdb2a38..59e1af67d 100644 --- a/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses +++ b/wadsrc/static/filter/duke.worldtour/rmapinfo.spawnclasses @@ -5,4 +5,6 @@ spawnclasses 5736 = DukeGenericDestructible, "WTGLASS1", "", "GLASS_BREAKING", spawnglass 5737 = DukeGenericDestructible, "WTGLASS2", "", "GLASS_BREAKING", spawnglass 5294 = DeveloperCommentary + 1891 = DukeFlamethrowerFlame + 5296 = DukeFireflyFlyingEffect } diff --git a/wadsrc/static/filter/redneck/rmapinfo.spawnclasses b/wadsrc/static/filter/redneck/rmapinfo.spawnclasses index dae0b8098..5601cee0e 100644 --- a/wadsrc/static/filter/redneck/rmapinfo.spawnclasses +++ b/wadsrc/static/filter/redneck/rmapinfo.spawnclasses @@ -125,6 +125,7 @@ spawnclasses 1083 = DukeCameraPole 26 = RedneckDynamite + 27 = RedneckPowderKeg 1416 = RedneckMortar 285 = RedneckChickenSpawner1 286 = RedneckChickenSpawner2 diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 0d28984f8..c2afa48e0 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -102,7 +102,10 @@ version "4.10" #include "zscript/games/duke/actors/bloodpool.zs" #include "zscript/games/duke/actors/toilet.zs" +#include "zscript/games/duke/actors/flamethrowerflame.zs" +#include "zscript/games/duke/actors/firefly.zs" +#include "zscript/games/duke/actors/powderkeg.zs" #include "zscript/games/duke/actors/redneckmisc.zs" #include "zscript/games/duke/actors/emptybike.zs" #include "zscript/games/duke/actors/rrteleport.zs" diff --git a/wadsrc/static/zscript/coreactor.zs b/wadsrc/static/zscript/coreactor.zs index 4169c41ba..8ad6ce4dd 100644 --- a/wadsrc/static/zscript/coreactor.zs +++ b/wadsrc/static/zscript/coreactor.zs @@ -57,6 +57,7 @@ class CoreActor native native double pitch; native Vector3 vel; native double viewzoffset; + native double oviewzoffset; native readonly int16 spritesetindex; native readonly int spawnindex; diff --git a/wadsrc/static/zscript/games/duke/actors/firefly.zs b/wadsrc/static/zscript/games/duke/actors/firefly.zs new file mode 100644 index 000000000..3d219107d --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/firefly.zs @@ -0,0 +1,47 @@ + +// for now only the effect is scriptified. + +class DukeFireflyFlyingEffect : DukeActor +{ + default + { + pic "FIREFLYFLYINGEFFECT"; + } + + override void Initialize() + { + self.scale = (0.25, 0.25); + self.ChangeStat(STAT_MISC); + } + + override void Tick() + { + Super.Tick(); + if (bDestroyed) return; // killed by script. + + + let Owner = self.ownerActor; + if (!Owner || !Owner.checkType("FIREFLY")) + { + self.Destroy(); + return; + } + + if (Owner.scale.X >= 0.375 || Owner.pal == 1) + self.cstat |= CSTAT_SPRITE_INVISIBLE; + else + self.cstat &= ~CSTAT_SPRITE_INVISIBLE; + + let p = self.findplayer(); + let dvec = Owner.pos.XY - p.actor.pos.XY; + double dist = dvec.Length(); + + if (dist != 0.0) dvec /= dist; + self.pos = Owner.pos + (dvec.X * -0.625, dvec.Y * -0.625, 8); + + if (Owner.extra <= 0) + { + self.Destroy(); + } + } +} diff --git a/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs b/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs new file mode 100644 index 000000000..90d8ec331 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/flamethrowerflame.zs @@ -0,0 +1,192 @@ +class DukeFlamethrowerFlame : DukeActor +{ + default + { + pic "FLAMETHROWERFLAME"; + } + + override void Tick() + { + Console.Printf("ticky"); + let sectp = self.sector; + double xx; + Super.Tick(); // Run CON or its replacement. + if (self.bDestroyed) return; // killed by script. + self.temp_data[0]++; + if (sectp.lotag == ST_2_UNDERWATER) + { + let spawned = self.spawn("DukeExplosion2"); + if (spawned) spawned.shade = 127; + self.Destroy(); + return; + } + + let dapos = self.pos; + + self.getglobalz(); + + int ds = self.temp_data[0] / 6; + if (self.scale.X < 0.1250) + { + self.scale.X += (ds * REPEAT_SCALE); + self.scale.Y = (self.scale.X); + } + self.clipdist += ds * 0.25; + if (self.temp_data[0] <= 2) + self.temp_data[3] = random(0, 9); + if (self.temp_data[0] > 30) + { + let spawned = self.spawn("DukeExplosion2"); + if (spawned) spawned.shade = 127; + self.Destroy(); + return; + } + + CollisionData coll; + self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK1, coll); + + if (self.sector == null) + { + self.Destroy(); + return; + } + + if (coll.type != kHitSprite) + { + if (self.pos.Z < self.ceilingz) + { + coll.setSector(self.sector); + self.vel.Z -= 1/256.; + } + else if ((self.pos.Z > self.floorz && self.sector.lotag != ST_1_ABOVE_WATER) + || (self.pos.Z > self.floorz + 16 && self.sector.lotag == ST_1_ABOVE_WATER)) + { + coll.setSector(self.sector); + if (self.sector.lotag != 1) + self.vel.Z += 1/256.; + } + } + + if (coll.type != 0) + { + self.vel.XY = (0, 0); + self.vel.Z = 0; + if (coll.type == kHitSprite) + { + let hitact = DukeActor(coll.hitActor()); + hitact.checkhitsprite(self); + if (hitact.isPlayer()) + hitact.PlayActorSound("PISTOL_BODYHIT"); + } + else if (coll.type == kHitWall) + { + self.SetPosition(dapos); + dlevel.checkhitwall(coll.hitWall(), self, self.pos); + } + else if (coll.type == kHitSector) + { + self.SetPosition(dapos); + if (self.vel.Z < 0) + dlevel.checkhitceiling(self.sector, self); + } + + if (self.scale.X >= 0.15625) + { + int x = self.extra; + self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); + } + else + { + int x = self.extra + (Duke.global_random() & 3); + self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); + } + } + } + + //--------------------------------------------------------------------------- + // + // + // + //--------------------------------------------------------------------------- + + override bool shootthis(DukeActor actor, DukePlayer p, Vector3 spos, double sang) const + { + Console.Printf("launching"); + double vel, zvel = 0; + + if (actor.extra >= 0) + actor.shade = -96; + vel = 25; + + DukeActor spawned = nullptr; + if (p == null) + { + double x; + DukePlayer j; + [j, x] = actor.findplayer(); + sang = (j.Actor.opos.XY - spos.XY).Angle(); + + if (actor.checktype("BOSS5")) + { + vel = 33; + spos.Z += 24; + } + else if (actor.checktype("BOSS3")) + spos.Z -= 32; + + double dist = (j.actor.pos.XY - actor.pos.XY).Length(); + if (dist != 0) + zvel = (((j.actor.opos.Z + j.actor.oviewzoffset - spos.Z) * vel) / dist); + + if (actor.badguy() && (actor.hitag & face_player_smart) != 0) + sang = actor.Angle + Raze.BAngToDegree * random(-16, 15); + + } + else + { + [vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 40.5); + + // WTF??? + double myang = 90. - (180. - abs(abs((spos.XY - p.actor.pos.XY).Angle() - sang) - 180.)); + if (p.actor.vel.X != 0) + vel = ((myang / 90.) * p.actor.vel.X) + 25; + } + + if (actor.sector.lotag == ST_2_UNDERWATER && (random(0, 4)) == 0) + spawned = actor.spawn("DukeWaterBubble"); + + if (spawned == nullptr) + { + spawned = actor.spawn("DukeFlamethrowerFlame"); + if (!spawned) return true; + spawned.vel.X = vel; + spawned.vel.Z = zvel; + } + + + Vector3 offset; + offset.X = cos(sang + Raze.BAngToDegree * 118) * (1024 / 448.); // Yes, these angles are really different! + offset.Y = sin(sang + Raze.BAngToDegree * 112) * (1024 / 448.); + offset.Z = -1; + + spawned.pos = spos + offset; + spawned.pos.Z--; + spawned.sector = actor.sector; + spawned.cstat = CSTAT_SPRITE_YCENTER; + spawned.Angle = sang; + spawned.scale = (0.03125, 0.03125); + spawned.clipdist = 10; + spawned.yint = Duke.GetPlayerIndex(p); + spawned.ownerActor = actor; + + if (p == null) + { + if (actor.checktype("BOSS5")) + { + spawned.pos += sang.ToVector() * (128. / 7); + spawned.scale = (0.15625, 0.15625); + } + } + return true; + } +} diff --git a/wadsrc/static/zscript/games/duke/actors/greenslime.zs b/wadsrc/static/zscript/games/duke/actors/greenslime.zs index e95d0fdf4..fcc83a441 100644 --- a/wadsrc/static/zscript/games/duke/actors/greenslime.zs +++ b/wadsrc/static/zscript/games/duke/actors/greenslime.zs @@ -7,7 +7,6 @@ class DukeGreenSlime : DukeActor override void Initialize() { - commonEnemySetup(); self.scale = (0.625, 0.625); self.clipdist = 20; self.extra = 1; diff --git a/wadsrc/static/zscript/games/duke/actors/powderkeg.zs b/wadsrc/static/zscript/games/duke/actors/powderkeg.zs new file mode 100644 index 000000000..19d9a9053 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/powderkeg.zs @@ -0,0 +1,34 @@ + +class RedneckPowderKeg : DukeActor +{ + default + { + pic "POWDERKEG"; + } + + override void Tick() + { + let sectp = self.sector; + if (sectp.lotag != ST_1_ABOVE_WATER && sectp.lotag != ST_160_FLOOR_TELEPORT) + if (self.vel.X != 0) + { + movesprite((self.Angle.ToVector()* self.vel.X, self.vel.Z), CLIPMASK0); + self.vel.X -= 1. / 16.; + } + Super.Tick(); + } + + + override bool shootthis(DukeActor actor, DukePlayer p, Vector3 spos, double sang) + { + let j = actor.spawn("RedneckPowderKeg"); + if (j) + { + j.vel.X = 2; + j.Angle = actor.Angle; + j.pos.Z -= 5; + } + return true; + } + +} diff --git a/wadsrc/static/zscript/games/duke/actors/recon.zs b/wadsrc/static/zscript/games/duke/actors/recon.zs index 645c1a164..eb5052c07 100644 --- a/wadsrc/static/zscript/games/duke/actors/recon.zs +++ b/wadsrc/static/zscript/games/duke/actors/recon.zs @@ -13,36 +13,12 @@ class DukeRecon : DukeActor override void initialize() { - if (self.lotag > ud.player_skill) - { - self.scale = (0, 0); - self.ChangeStat(STAT_MISC); - return; - } - if (!Raze.isRR() || self.actorflag1(SFLAG_KILLCOUNT)) // in Duke bad guys always count as kill. RR uses a flag. Needs to be cleaned up. - Duke.GetLocalPlayer().max_actors_killed++; self.temp_data[5] = 0; - if (ud.monsters_off == 1) - { - self.scale = (0, 0); - self.ChangeStat(STAT_MISC); - return; - } self.extra = 130; - - self.cstat |= CSTAT_SPRITE_BLOCK_ALL; // Make it hitable - - if (ud.multimode < 2 && self.pal != 0) - { - self.scale = (0, 0); - self.ChangeStat(STAT_MISC); - return; - } self.pal = 0; self.shade = -17; - self.ChangeStat(STAT_ZOMBIEACTOR); - + AttackSnd = "RECO_ATTACK"; PainSnd = "RECO_PAIN"; RoamSnd = "RECO_ROAM"; diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 7e8cf73cb..55bf04734 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -115,6 +115,28 @@ class DukeActor : CoreActor native STAT_REMOVED = MAXSTATUS-2, }; + + enum amoveflags_t + { + face_player = 1, + geth = 2, + getv = 4, + random_angle = 8, + face_player_slow = 16, + spin = 32, + face_player_smart = 64, + fleeenemy = 128, + jumptoplayer_only = 256, + justjump1 = 256, + jumptoplayer = 257, + seekplayer = 512, + furthestdir = 1024, + dodgebullet = 4096, + justjump2 = 8192, + windang = 16384, + antifaceplayerslow = 32768 + }; + native void SetSpritesetImage(int index); native int GetSpritesetSize(); @@ -187,7 +209,6 @@ class DukeActor : CoreActor native virtual void BeginPlay() {} virtual void StaticSetup() {} - virtual void Initialize() {} virtual void onHit(DukeActor hitter) { checkhitdefault(hitter); } virtual void onHurt(DukePlayer p) {} virtual bool onUse(DukePlayer user) { return false; } @@ -208,6 +229,7 @@ class DukeActor : CoreActor native native void hitradius(int r, int hp1, int hp2, int hp3, int hp4); native double, DukeActor hitasprite(); native int badguy(); + native int scripted(); native int isplayer(); native void lotsofstuff(Name type, int count); native double gutsoffset(); @@ -229,33 +251,26 @@ class DukeActor : CoreActor native deprecated("4.9") native bool checktype(String name); // this must not stay in the code, so mark it deprecated to keep the annoying warning at startup. - void commonEnemySetup(bool countkill = true) + + virtual void Initialize() { - if (!self.mapSpawned) self.lotag = 0; - - if ((self.lotag > ud.player_skill) || ud.monsters_off == 1) + if (!self.badguy() && self.scripted()) { - self.scale = (0, 0); - self.ChangeStat(STAT_MISC); - } - else - { - self.makeitfall(); + if (!self.mapSpawned) self.lotag = 0; - self.cstat |= CSTAT_SPRITE_BLOCK_ALL; - if (countkill) - Duke.GetLocalPlayer().max_actors_killed++; - - if (!self.mapSpawned) + if (self.lotag > ud.player_skill) { - self.timetosleep = 0; - self.PlayFTASound(); - self.ChangeStat(STAT_ACTOR); + self.scale = (0, 0); + self.ChangeStat(STAT_MISC); } - else self.ChangeStat(STAT_ZOMBIEACTOR); + self.clipdist = 10; + self.ownerActor = self; + self.ChangeStat(STAT_ACTOR); } + } + int checkLocationForFloorSprite(double radius) { bool away = self.isAwayFromWall(radius); diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index 90f66dd88..aeb545fb6 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -170,6 +170,7 @@ struct Duke native native static void updatepindisplay(int tag, int pinmask); native static bool StartCommentary(int tag, DukeActor act); native static void StopCommentary(); + static native int getPlayerIndex(DukePlayer p); static int rnd(int val) { return (random(0, 255) >= (255 - (val))); @@ -216,6 +217,7 @@ struct Duke native if (align != -1) x -= myfont.StringWidth(t) * (align == 0 ? 0.5 : 1); Screen.DrawText(myfont, Font.CR_NATIVEPAL, x, y + 2, t, DTA_FullscreenScale, fsmode, DTA_TranslationIndex, Translation.MakeID(Translation_Remap, trans), DTA_Color, Raze.shadeToLight(shade)); } + } struct DukePlayer native diff --git a/wadsrc/static/zscript/razebase.zs b/wadsrc/static/zscript/razebase.zs index 65ba5a27e..a3f412e33 100644 --- a/wadsrc/static/zscript/razebase.zs +++ b/wadsrc/static/zscript/razebase.zs @@ -264,6 +264,11 @@ struct Raze // Right now, with no MP support there is no need, though. } + static double, double setFreeAimVelocity(double vel, double zvel, double pitch, double zvspeed) + { + return vel * cos(pitch), sin(pitch) * zvspeed; + } + } /*