From 76fabcd1c7c634c05fbde346aa878c18ab970170 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 21 Nov 2022 08:15:41 +0100 Subject: [PATCH] - chickenplant scriptified. --- source/games/duke/src/actors_r.cpp | 178 +------- source/games/duke/src/animatesprites_r.cpp | 4 +- source/games/duke/src/flags_r.cpp | 4 +- source/games/duke/src/global.cpp | 1 - source/games/duke/src/namelist_r.h | 8 +- source/games/duke/src/premap.cpp | 2 +- source/games/duke/src/premap_r.cpp | 8 +- source/games/duke/src/savegame.cpp | 2 +- source/games/duke/src/sectors_r.cpp | 16 +- source/games/duke/src/spawn_r.cpp | 64 +-- source/games/duke/src/types.h | 1 + source/games/duke/src/vmexports.cpp | 129 ++++-- .../static/filter/redneck/engine/engine.def | 19 + wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/coreactor.zs | 9 + .../zscript/games/duke/actors/chickenplant.zs | 391 ++++++++++++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 6 + wadsrc/static/zscript/games/duke/dukegame.zs | 2 +- 18 files changed, 559 insertions(+), 286 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/chickenplant.zs diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index e8d57a85f..6291c98e3 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -432,7 +432,7 @@ int movesprite_ex_r(DDukeActor* actor, const DVector3& change, unsigned int clip void lotsoffeathers_r(DDukeActor *actor, int n) { - lotsofstuff(actor, n, MONEY); + lotsofstuff(actor, n, FEATHER); } @@ -715,7 +715,7 @@ static void chickenarrow(DDukeActor* actor) if (spawned) spawned->spr.pos.Z += 1; if ((krand() & 15) == 2) { - spawn(actor, MONEY); + spawn(actor, FEATHER); } } DDukeActor* ts = actor->seek_actor; @@ -1917,91 +1917,9 @@ void rr_specialstats() } } - if (chickenplant) + if (ud.chickenplant) { - it.Reset(STAT_CHICKENPLANT); - while (auto act = it.Next()) - { - switch (act->spr.picnum) - { - case CHICKENASPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, CHICKENA)->spr.angle = act->spr.angle; - act->spr.lotag = 128; - } - break; - case CHICKENCSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, CHICKENC)->spr.angle = act->spr.angle; - act->spr.lotag = 256; - } - break; - case FEATHERSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - lotsoffeathers_r(act, (krand() & 3) + 4); - act->spr.lotag = 84; - } - break; - case CHICKENHEADSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - auto j = spawn(act, CHICKENHEAD); - act->spr.lotag = 96; - if (j && !isRRRA()) S_PlayActorSound(472, j); - } - break; - case LOAFSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, CHICKENLOAF)->spr.angle = act->spr.angle; - act->spr.lotag = 448; - } - break; - case NUGGETSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, CHICKENNUGGET)->spr.angle = act->spr.angle; - act->spr.lotag = 64; - } - break; - case ROASTSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, ROASTEDCHICKEN)->spr.angle = act->spr.angle; - act->spr.lotag = 512; - } - break; - case BONELESSSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - spawn(act, BONELESSCHICKEN)->spr.angle = act->spr.angle; - act->spr.lotag = 224; - } - break; - case JIBSSPAWN: - act->spr.lotag--; - if (act->spr.lotag < 0) - { - fi.guts(act, JIBS1, 1, myconnectindex); - fi.guts(act, JIBS2, 1, myconnectindex); - fi.guts(act, JIBS3, 1, myconnectindex); - fi.guts(act, JIBS4, 1, myconnectindex); - act->spr.lotag = 256; - } - break; - } - } + tickstat(STAT_CHICKENPLANT); } it.Reset(STAT_BOWLING); @@ -2425,94 +2343,6 @@ void moveactors_r(void) case RAT: if (!rat(act, !isRRRA())) continue; break; - case CHICKENA: - case CHICKENB: - case CHICKENC: - if (!chickenplant) - { - act->Destroy(); - continue; - } - if (sectp->lotag == 903) - makeitfall(act); - movesprite_ex(act, DVector3(act->spr.angle.ToVector() * act->vel.X, act->vel.Z), CLIPMASK0, coll); - switch (sectp->lotag) - { - case 901: - act->spr.picnum = CHICKENB; - break; - case 902: - act->spr.picnum = CHICKENC; - break; - case 903: - if (act->spr.pos.Z >= sectp->floorz - 8) - { - act->Destroy(); - continue; - } - break; - case 904: - act->Destroy(); - continue; - break; - } - if (coll.type > kHitSector) - { - act->Destroy(); - continue; - } - break; - - case CHICKENLOAF: - case CHICKENNUGGET: - case ROASTEDCHICKEN: - case BONELESSCHICKEN: - if (!chickenplant) - { - act->Destroy(); - continue; - } - makeitfall(act); - movesprite_ex(act, DVector3(act->spr.angle.ToVector() * act->vel.X, act->vel.Z), CLIPMASK0, coll); - if (coll.type > kHitSector) - { - act->Destroy(); - continue; - } - if (sectp->lotag == 903) - { - if (act->spr.pos.Z >= sectp->floorz - 4) - { - act->Destroy(); - continue; - } - } - else if (sectp->lotag == 904) - { - act->Destroy(); - continue; - } - break; - - case CHICKENHEAD: - if (!chickenplant) - { - act->Destroy(); - continue; - } - makeitfall(act); - movesprite_ex(act, DVector3(act->spr.angle.ToVector() * act->vel.X, act->vel.Z), CLIPMASK0, coll); - if (act->spr.pos.Z >= sectp->floorz - 8) - { - if (sectp->lotag == 1) - { - auto j = spawn(act, WATERSPLASH2); - if (j) j->spr.pos.Z = j->sector()->floorz; - } - act->Destroy(); - continue; - } - break; case BOWLINGBALL: if (act->vel.X != 0) { diff --git a/source/games/duke/src/animatesprites_r.cpp b/source/games/duke/src/animatesprites_r.cpp index d1b57cc21..8afa2cfba 100644 --- a/source/games/duke/src/animatesprites_r.cpp +++ b/source/games/duke/src/animatesprites_r.cpp @@ -201,8 +201,8 @@ void animatesprites_r(tspriteArray& tsprites, const DVector2& viewVec, DAngle vi case FOOTPRINTS4: if (t->pal == 6) t->shade = -127; - case MONEY: - case MONEY + 1: + case FEATHER: + case FEATHER + 1: break; case POWDERKEG: continue; diff --git a/source/games/duke/src/flags_r.cpp b/source/games/duke/src/flags_r.cpp index 37ae5bbc4..c3d25e902 100644 --- a/source/games/duke/src/flags_r.cpp +++ b/source/games/duke/src/flags_r.cpp @@ -75,8 +75,8 @@ void initactorflags_r() TECHSWITCH + 1, DIPSWITCH3, DIPSWITCH3 + 1, - NUKEBUTTON, - NUKEBUTTON + 1 }); + CHICKENPLANTBUTTON, + CHICKENPLANTBUTTON + 1 }); if (isRRRA()) settileflag(TFLAG_WALLSWITCH, { MULTISWITCH2, MULTISWITCH2 + 1, diff --git a/source/games/duke/src/global.cpp b/source/games/duke/src/global.cpp index c445f2697..056866d25 100644 --- a/source/games/duke/src/global.cpp +++ b/source/games/duke/src/global.cpp @@ -60,7 +60,6 @@ int earthquaketime; int global_random; // readonly - one single global per-frame random value. Ugh... // Redneck Rampage -int chickenplant; // readonly - used to trigger some special behavior if a special item is found in a map. int thunderon; // readonly - enables thunder effect in RR if true. int ufospawn; // UFO spawn flag int ufocnt; // UFO spawn count diff --git a/source/games/duke/src/namelist_r.h b/source/games/duke/src/namelist_r.h index 5c7aa5830..11b06f02d 100644 --- a/source/games/duke/src/namelist_r.h +++ b/source/games/duke/src/namelist_r.h @@ -68,7 +68,7 @@ x(LIGHTSWITCH, 86) x(SPACEDOORSWITCH, 88) x(SPACELIGHTSWITCH, 90) x(FRANKENSTINESWITCH, 92) -x(NUKEBUTTON, 94) +x(CHICKENPLANTBUTTON, 94) x(MULTISWITCH, 98) x(DOORTILE1, 102) x(DOORTILE2, 103) @@ -171,8 +171,8 @@ x(ROASTSPAWN, 291) x(BONELESSSPAWN, 292) x(JIBSSPAWN, 293) x(KEGHOLDER, 295) // that's what the text on the sprite says. It doesn't seem to do anything. -y(RRTELEPORT, 296) -y(RRTELEPORTDEST, 297) +x(RRTELEPORT, 296) +x(RRTELEPORTDEST, 297) x(CDPLAYER, 370) y(RRTILE380, 380) x(BONUSPIC01, 403) @@ -406,7 +406,6 @@ x(NUKEBARREL, 1304) x(NUKEBARRELDENTED, 1305) x(NUKEBARRELLEAKED, 1306) x(CANWITHSOMETHING, 1309) -x(MONEY, 1310) x(FEATHER, 1310) x(BANNER, 1313) x(EXPLODINGBARREL, 1315) @@ -884,7 +883,6 @@ y(RRTILE3115, 3115) y(RRTILE3116, 3116) y(RRTILE3117, 3117) x(CHICKENLOAF, 3120) -y(RRTILE3121, 3121) x(CHICKENNUGGET, 3122) x(ROASTEDCHICKEN, 3123) x(BONELESSCHICKEN, 3124) diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp index 1e1bde2dd..85aae4714 100644 --- a/source/games/duke/src/premap.cpp +++ b/source/games/duke/src/premap.cpp @@ -660,7 +660,7 @@ void prelevel_common(int g) geocnt = 0; ambienttags.Clear(); thunderon = 0; - chickenplant = 0; + ud.chickenplant = 0; WindTime = 0; WindDir = nullAngle; fakebubba_spawn = 0; diff --git a/source/games/duke/src/premap_r.cpp b/source/games/duke/src/premap_r.cpp index 406c922ff..77922ed3e 100644 --- a/source/games/duke/src/premap_r.cpp +++ b/source/games/duke/src/premap_r.cpp @@ -534,6 +534,10 @@ void prelevel_r(int g, TArray& actors) { ps[0].Exit = ac->spr.pos.XY(); } + else if (ac->spr.picnum == CHICKENPLANTBUTTON) + { + ud.chickenplant = 1; + } else { premapcontroller(ac); @@ -624,8 +628,8 @@ void prelevel_r(int g, TArray& actors) case POWERSWITCH1 + 1: case LOCKSWITCH1 + 1: case POWERSWITCH2 + 1: - case NUKEBUTTON: - case NUKEBUTTON + 1: + case CHICKENPLANTBUTTON: + case CHICKENPLANTBUTTON + 1: for (j = 0; j < lotaglist; j++) if (ac->spr.lotag == lotags[j]) diff --git a/source/games/duke/src/savegame.cpp b/source/games/duke/src/savegame.cpp index d30d34d10..3d8250405 100644 --- a/source/games/duke/src/savegame.cpp +++ b/source/games/duke/src/savegame.cpp @@ -380,6 +380,7 @@ void GameInterface::SerializeGameState(FSerializer& arc) ("numplayersprites", numplayersprites) ("spriteqloc", spriteqloc) ("animates", animates) + ("chickenplant", ud.chickenplant) ("numclouds", numclouds) ("cloudx", cloudx) @@ -393,7 +394,6 @@ void GameInterface::SerializeGameState(FSerializer& arc) .Array("mirrorsector", mirrorsector, mirrorcnt) .Array("mirrorwall", mirrorwall, mirrorcnt) ("wupass", wupass) - ("chickenplant", chickenplant) ("thunderon", thunderon) ("ufospawn", ufospawn) ("ufocnt", ufocnt) diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index 55c937065..0b019bd0f 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -437,8 +437,8 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act) case LOCKSWITCH1 + 1: case POWERSWITCH2: case POWERSWITCH2 + 1: - case NUKEBUTTON: - case NUKEBUTTON + 1: + case CHICKENPLANTBUTTON: + case CHICKENPLANTBUTTON + 1: case RRTILE2214: case RRTILE2697: case RRTILE2697 + 1: @@ -510,7 +510,7 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act) case PULLSWITCH: case DIPSWITCH2: case DIPSWITCH3: - case NUKEBUTTON: + case CHICKENPLANTBUTTON: case RRTILE2697: case RRTILE2707: if (other->spr.picnum == DIPSWITCH3) @@ -532,8 +532,8 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act) other->spr.picnum++; break; } - if (other->spr.picnum == NUKEBUTTON) - chickenplant = 0; + if (other->spr.picnum == CHICKENPLANTBUTTON) + ud.chickenplant = 0; if (other->spr.picnum == RRTILE8660) { BellTime = 132; @@ -554,11 +554,11 @@ bool checkhitswitch_r(int snum, walltype* wwal, DDukeActor* act) case FRANKENSTINESWITCH + 1: case DIPSWITCH2 + 1: case DIPSWITCH3 + 1: - case NUKEBUTTON + 1: + case CHICKENPLANTBUTTON + 1: case RRTILE2697 + 1: case RRTILE2707 + 1: - if (other->spr.picnum == NUKEBUTTON + 1) - chickenplant = 1; + if (other->spr.picnum == CHICKENPLANTBUTTON + 1) + ud.chickenplant = 1; if (other->spr.hitag != 999) other->spr.picnum--; break; diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index 51bae9900..839bc40e5 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -145,22 +145,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* act->spr.extra = 0; ChangeActorStat(act, 122); break; - case CHICKENASPAWN: - case CHICKENCSPAWN: - case FEATHERSPAWN: - case CHICKENHEADSPAWN: - case LOAFSPAWN: - case NUGGETSPAWN: - case ROASTSPAWN: - case BONELESSSPAWN: - case JIBSSPAWN: - act->spr.cstat = 0; - act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; - act->spr.scale = DVector2(0, 0); - act->clipdist = 0; - act->spr.lotag = 0; - ChangeActorStat(act, STAT_CHICKENPLANT); - break; case RRTILE2460: case RRTILE2465: @@ -461,50 +445,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* act->clipdist = 16; ChangeActorStat(act, STAT_TELEPORT); break; - case CHICKENA: - case CHICKENB: - case CHICKENC: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 2; - act->spr.scale = DVector2(0.5, 0.40625); - act->vel.X = 2; - ChangeActorStat(act, STAT_ACTOR); - break; - case CHICKENLOAF: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 2; - act->spr.scale = DVector2(0.1875, 0.15625); - act->vel.X = 2; - ChangeActorStat(act, STAT_ACTOR); - break; - case CHICKENNUGGET: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 0.5; - act->spr.scale = DVector2(0.125, 0.09375); - act->vel.X = 1; - ChangeActorStat(act, STAT_ACTOR); - break; - case ROASTEDCHICKEN: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 2; - act->spr.scale = DVector2(0.203125, 0.203125); - act->vel.X = 1; - ChangeActorStat(act, STAT_ACTOR); - break; - case BONELESSCHICKEN: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 2; - act->spr.scale = DVector2(0.265625, 0.1875); - act->vel.X = 2; - ChangeActorStat(act, STAT_ACTOR); - break; - case CHICKENHEAD: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 2; - act->spr.scale = DVector2(0.203125, 0.15625); - act->vel.X = 0; - ChangeActorStat(act, STAT_ACTOR); - break; case BOWLINGPIN: act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; act->clipdist = 12; @@ -548,8 +488,8 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* act->spr.cstat = CSTAT_SPRITE_ALIGNMENT_WALL | randomFlip(); insertspriteq(act); [[fallthrough]]; - case MONEY: - if (act->spr.picnum == MONEY) + case FEATHER: + if (act->spr.picnum == FEATHER) { act->temp_data[0] = krand() & 2047; act->spr.cstat = randomFlip(); diff --git a/source/games/duke/src/types.h b/source/games/duke/src/types.h index 636184e2f..865cd02fe 100644 --- a/source/games/duke/src/types.h +++ b/source/games/duke/src/types.h @@ -161,6 +161,7 @@ struct user_defs int m_respawn_items, m_respawn_monsters, m_respawn_inventory, m_recstat, m_monsters_off; int m_ffire, ffire, m_player_skill, multimode; int player_skill, marker; + int chickenplant; // readonly - used to trigger some special behavior if a special item is found in a map. TObjPtr cameraactor; diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index b8f2ffd98..9ca9e8792 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -1,5 +1,58 @@ BEGIN_DUKE_NS +// Workaround so that the script code can be written in its final form. This must go away later. +int PicForName(int intname) +{ + int picnum = -1; + // this is still a hack so it can spawn actors which haven't been scriptified yet. This will go away later. + if (FName(ENamedName(intname)) == FName("DukeToiletWater")) + { + picnum = TileFiles.tileForName("TOILETWATER"); + } + else if (FName(ENamedName(intname)) == FName("DukeBurning")) + { + picnum = TileFiles.tileForName("BURNIMG"); + } + else if (FName(ENamedName(intname)) == FName("DukeBloodPool")) + { + picnum = TileFiles.tileForName("BLOODPOOL"); + } + else if (FName(ENamedName(intname)) == FName("DukeExplosion2")) + { + picnum = TileFiles.tileForName("EXPLOSION2"); + } + else if (FName(ENamedName(intname)) == FName("DukeTransporterStar")) + { + picnum = TileFiles.tileForName("TRANSPORTERSTAR"); + } + else if (FName(ENamedName(intname)) == FName("RedneckRabbit")) + { + picnum = TileFiles.tileForName("RABBIT"); + } + else if (FName(ENamedName(intname)) == FName("DukeJibs1")) + { + picnum = TileFiles.tileForName("JIBS1"); + } + else if (FName(ENamedName(intname)) == FName("DukeJibs2")) + { + picnum = TileFiles.tileForName("JIBS2"); + } + else if (FName(ENamedName(intname)) == FName("DukeJibs3")) + { + picnum = TileFiles.tileForName("JIBS3"); + } + else if (FName(ENamedName(intname)) == FName("DukeJibs4")) + { + picnum = TileFiles.tileForName("JIBS4"); + } + else if (FName(ENamedName(intname)) == FName("RedneckFeather")) + { + picnum = TileFiles.tileForName("FEATHER"); + } + return picnum; +} + + //--------------------------------------------------------------------------- // // global exports @@ -249,33 +302,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, StopSound, DukeActor_StopSound) DDukeActor* DukeActor_Spawn(DDukeActor* origin, int intname) { - int picnum = -1; - // this is still a hack so it can spawn actors which haven't been scriptified yet. This will go away later. - if (FName(ENamedName(intname)) == FName("DukeToiletWater")) - { - picnum = TileFiles.tileForName("TOILETWATER"); - } - else if (FName(ENamedName(intname)) == FName("DukeBurning")) - { - picnum = TileFiles.tileForName("BURNIMG"); - } - else if (FName(ENamedName(intname)) == FName("DukeBloodPool")) - { - picnum = TileFiles.tileForName("BLOODPOOL"); - } - else if (FName(ENamedName(intname)) == FName("DukeExplosion2")) - { - picnum = TileFiles.tileForName("EXPLOSION2"); - } - else if (FName(ENamedName(intname)) == FName("DukeTransporterStar")) - { - picnum = TileFiles.tileForName("TRANSPORTERSTAR"); - } - else if (FName(ENamedName(intname)) == FName("RedneckRabbit")) - { - picnum = TileFiles.tileForName("RABBIT"); - } - + int picnum = PicForName(intname); if (picnum == -1) { @@ -296,6 +323,53 @@ DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, spawn, DukeActor_Spawn) ACTION_RETURN_POINTER(DukeActor_Spawn(self, type)); } +void DukeActor_Lotsofstuff(DDukeActor* actor, int count, int intname) +{ + int picnum = PicForName(intname); + // Todo: make this class aware. + lotsofstuff(actor, count, picnum); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, lotsofstuff, DukeActor_Lotsofstuff) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + PARAM_INT(type); + PARAM_INT(count); + DukeActor_Lotsofstuff(self, count, type); + return 0; +} + +void DukeActor_spawnguts(DDukeActor* actor, int count, int intname) +{ + int picnum = PicForName(intname); + fi.guts(actor, picnum, count, myconnectindex); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, spawnguts, DukeActor_spawnguts) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + PARAM_INT(type); + PARAM_INT(count); + DukeActor_spawnguts(self, count, type); + return 0; +} + +int DukeActor_movesprite(DDukeActor* actor, double velx, double vely, double velz, int clipmask) +{ + Collision coll; + return movesprite_ex(actor, DVector3(velx, vely, velz), clipmask, coll); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DDukeActor, movesprite, DukeActor_movesprite) +{ + PARAM_SELF_PROLOGUE(DDukeActor); + PARAM_FLOAT(velx); + PARAM_FLOAT(vely); + PARAM_FLOAT(velz); + PARAM_INT(clipmask); + ACTION_RETURN_INT(DukeActor_movesprite(self, velx, vely, velz, clipmask)); +} + DDukeActor* DukeActor_Spawnsprite(DDukeActor* origin, int picnum) { if (picnum >= 0 && picnum < MAXTILES) @@ -980,6 +1054,7 @@ 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_FIELD_X(DukeUserDefs, user_defs, chickenplant); DEFINE_GLOBAL_UNSIZED(ud) diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index b00f02221..98e90e92c 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -47,5 +47,24 @@ spawnclasses 1439 = DukeInnerJaw 1440 = DukeInnerJaw1 + 285 = RedneckChickenSpawner1 + 286 = RedneckChickenSpawner2 + 287 = RedneckFeatherSpawner + 288 = RedneckChickenHeadSpawner + 289 = RedneckChickenLoafSpawner + 290 = RedneckChickenNuggetSpawner + 291 = RedneckChickenRoastSpawner + 292 = RedneckBonelessSpawner + 293 = RedneckJibsSpawner + 7525 = RedneckRabbitSpawner + 3190 = RedneckChickenA + 3191 = RedneckChickenB + 3192 = RedneckChickenC + 3120 = RedneckChickenLoaf + 3122 = RedneckChickenNugget + 3123 = RedneckRoastedChicken + 3124 = RedneckBonelessChicken + 3132 = RedneckChickenHead + } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 8d4ccd016..07e04d241 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -74,6 +74,7 @@ version "4.10" #include "zscript/games/duke/actors/tongue.zs" #include "zscript/games/duke/actors/rabbitspawner.zs" +#include "zscript/games/duke/actors/chickenplant.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 424c1a3eb..ccc60df09 100644 --- a/wadsrc/static/zscript/coreactor.zs +++ b/wadsrc/static/zscript/coreactor.zs @@ -5,6 +5,15 @@ enum EClipMask CLIPMASK1 = (256 << 16) + 64 }; +enum EHitBits +{ + kHitNone = 0, + kHitSector = 0x4000, + kHitWall = 0x8000, + kHitSprite = 0xC000, + kHitVoid = 0x10000, // SW only +}; + const MAXPLAYERS = 8; const MAXSTATUS = 1024; const zmaptoworld = (1. / 256.); diff --git a/wadsrc/static/zscript/games/duke/actors/chickenplant.zs b/wadsrc/static/zscript/games/duke/actors/chickenplant.zs new file mode 100644 index 000000000..5e3c17472 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/chickenplant.zs @@ -0,0 +1,391 @@ + +class RedneckChickenSpawner1 : DukeActor +{ + default + { + scaleX 0; + scaleY 0; + clipdist 0; + lotag 0; + statnum STAT_CHICKENPLANT; + pic "CHICKENASPAWN"; + } + + override void Initialize() + { + self.cstat = CSTAT_SPRITE_INVISIBLE; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenA'); + if (spawned) spawned.angle = self.angle; + self.lotag = 128; + } + } +} + +class RedneckChickenSpawner2 : RedneckChickenSpawner1 +{ + default + { + pic "CHICKENCSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenC'); + if (spawned) spawned.angle = self.angle; + self.lotag = 256; + } + } +} + +class RedneckFeatherSpawner : RedneckChickenSpawner1 +{ + default + { + pic "FEATHERSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + self.lotsofstuff('RedneckFeather', random(4, 7)); + self.lotag = 84; + } + } +} + +class RedneckChickenHeadSpawner : RedneckChickenSpawner1 +{ + default + { + pic "CHICKENHEADSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenHead'); + self.lotag = 96; + if (spawned && !Raze.isRRRA()) self.PlayActorSound(RRSnd.POOLBUD); + } + } +} + +class RedneckChickenLoafSpawner : RedneckChickenSpawner1 +{ + default + { + pic "LOAFSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenLoaf'); + if (spawned) spawned.angle = self.angle; + self.lotag = 448; + } + } +} + +class RedneckChickenNuggetSpawner : RedneckChickenSpawner1 +{ + default + { + pic "NUGGETSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenNugget'); + if (spawned) spawned.angle = self.angle; + self.lotag = 64; + } + } +} + +class RedneckChickenRoastSpawner : RedneckChickenSpawner1 +{ + default + { + pic "ROASTSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckChickenRoast'); + if (spawned) spawned.angle = self.angle; + self.lotag = 512; + } + } +} + +class RedneckBonelessSpawner : RedneckChickenSpawner1 +{ + default + { + pic "BONELESSSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + let spawned = self.spawn('RedneckBonelessChicken'); + if (spawned) spawned.angle = self.angle; + self.lotag = 224; + } + } +} + +class RedneckJibsSpawner : RedneckChickenSpawner1 +{ + default + { + pic "JIBSSPAWN"; + } + + override void Tick() + { + self.lotag--; + if (self.lotag < 0) + { + self.spawnguts('DukeJibs1', 1); + self.spawnguts('DukeJibs2', 1); + self.spawnguts('DukeJibs3', 1); + self.spawnguts('DukeJibs4', 1); + self.lotag = 256; + } + } +} + +//---------------------------------- + +class RedneckChickenA : DukeActor +{ + default + { + clipdist 2; + scaleX 0.5; + scaleY 0.40625; + statnum STAT_ACTOR; + spriteset "CHICKENA", "CHICKENB", "CHICKENC"; + } + + override void Initialize() + { + self.cstat = CSTAT_SPRITE_BLOCK_ALL; + self.vel.X = 2; + } + + override void Tick() + { + if (!ud.chickenplant) + { + self.Destroy(); + return; + } + let sectp = self.sector; + if (sectp.lotag == 903) + self.makeitfall(); + + int collision = self.movesprite((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0); + switch (sectp.lotag) + { + case 901: + self.SetSpritesetImage(1); + break; + case 902: + self.SetSpritesetImage(2); + break; + case 903: + if (self.pos.Z >= sectp.floorz - 8) + { + self.Destroy(); + return; + } + break; + case 904: + self.Destroy(); + break; + } + if (collision > kHitSector) + { + self.Destroy(); + } + } +} + +class RedneckChickenB : RedneckChickenA +{ + default + { + spritesetindex 1; + } +} + +class RedneckChickenC : RedneckChickenA +{ + default + { + spritesetindex 2; + } +} + +//---------------------------------- + +class RedneckChickenLoaf : DukeActor +{ + default + { + statnum STAT_ACTOR; + clipdist 2; + scaleX 0.1875; + scaleY 0.15625; + pic "CHICKENLOAF"; + } + + override void Initialize() + { + self.cstat = CSTAT_SPRITE_BLOCK_ALL; + self.vel.X = 2; + } + + override void Tick() + { + if (!ud.chickenplant) + { + self.Destroy(); + return; + } + self.makeitfall(); + let collision = self.movesprite((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0); + if (collision > kHitSector) + { + self.Destroy(); + return; + } + let sectp = self.sector; + if (sectp.lotag == 903) + { + if (self.pos.Z >= sectp.floorz - 4) + { + self.Destroy(); + return; + } + } + else if (sectp.lotag == 904) + { + self.Destroy(); + return; + } + } +} + +class RedneckRoastedChicken : RedneckChickenLoaf +{ + default + { + scaleX 0.203125; + scaleY 0.203125; + clipdist 2; + pic "ROASTEDCHICKEN"; + } + + override void Initialize() + { + self.vel.X = 1; + } +} + +class RedneckChickenNugget : RedneckChickenLoaf +{ + default + { + scaleX 0.125; + scaleY 0.09375; + clipdist 0.5; + pic "CHICKENNUGGET"; + } + + override void Initialize() + { + self.vel.X = 1; + } +} + +class RedneckBonelessChicken : RedneckChickenLoaf +{ + default + { + scaleX 0.265625; + scaleY 0.1875; + clipdist 2; + pic "BONELESSCHICKEN"; + } + + override void Initialize() + { + self.vel.X = 2; + } +} + +class RedneckChickenHead : DukeActor +{ + default + { + statnum STAT_ACTOR; + scaleX 0.203125; + scaleY 0.15625; + clipdist 2; + pic "CHICKENHEAD"; + } + + override void Initialize() + { + self.vel.X = 0; + } + + override void Tick() + { + if (!ud.chickenplant) + { + self.Destroy(); + return; + } + self.makeitfall(); + self.movesprite((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0); + if (self.pos.Z >= self.sector.floorz - 8) + { + if (self.sector.lotag == 1) + { + let j = self.spawn('DukeWaterSplash2'); + if (j) j.pos.Z = j.sector.floorz; + } + self.Destroy(); + } + } +} + diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 8f9db2a03..24e4c44fe 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -102,6 +102,9 @@ class DukeActor : CoreActor native STAT_DESTRUCT = 100, STAT_BOWLING = 105, + STAT_CHICKENPLANT = 106, + STAT_LUMBERMILL = 107, + STAT_TELEPORT = 108, STAT_RABBITSPAWN = 119, STAT_REMOVED = MAXSTATUS-2, @@ -185,6 +188,9 @@ class DukeActor : CoreActor native native void ChangeStat(int s, bool forcetail = false); native int badguy(); native int isplayer(); + native void lotsofstuff(Name type, int count); + native void spawnguts(Name type, int count); + native int movesprite(Vector3 move, int clipmask); // temporary flag accessors - need to be eliminated once we can have true actor flags diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index a578bc866..e4ea5deab 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -1307,7 +1307,7 @@ struct DukeUserDefs native 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 readonly int player_skill, marker, chickenplant; native int16 bomb_tag; native DukeActor cameraactor;