From 5a155730b4e593a8fa5aafa932bd5179d402b74a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 2 Dec 2022 16:26:31 +0100 Subject: [PATCH] - scriptified RR's bowling stuff. --- source/core/namedef_custom.h | 1 + source/core/vmexports.cpp | 9 + source/games/duke/src/actors_r.cpp | 152 +------- source/games/duke/src/bowling.cpp | 268 +------------- source/games/duke/src/hudweapon_r.cpp | 2 +- source/games/duke/src/namelist_r.h | 19 +- source/games/duke/src/player_r.cpp | 11 - source/games/duke/src/sectors_r.cpp | 34 -- source/games/duke/src/spawn_r.cpp | 34 -- source/games/duke/src/vmexports.cpp | 36 ++ .../static/filter/redneck/engine/engine.def | 7 + wadsrc/static/zscript.txt | 1 + .../zscript/games/duke/actors/bowling.zs | 338 ++++++++++++++++++ .../zscript/games/duke/actors/queball.zs | 13 +- wadsrc/static/zscript/games/duke/dukeactor.zs | 11 + wadsrc/static/zscript/games/duke/dukegame.zs | 1 + wadsrc/static/zscript/maptypes.zs | 18 + 17 files changed, 456 insertions(+), 499 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/bowling.zs diff --git a/source/core/namedef_custom.h b/source/core/namedef_custom.h index ecaa87c35..966b967a3 100644 --- a/source/core/namedef_custom.h +++ b/source/core/namedef_custom.h @@ -24,6 +24,7 @@ xx(DukeGlassPieces) xx(DukeGlassPieces1) xx(DukeGlassPieces2) xx(DukeNaturalLightning) +xx(RedneckBowlingPin) xx(spawnstate) xx(brokenstate) diff --git a/source/core/vmexports.cpp b/source/core/vmexports.cpp index 321a5293d..d86b8ab51 100644 --- a/source/core/vmexports.cpp +++ b/source/core/vmexports.cpp @@ -465,6 +465,15 @@ DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, getslopes, sector_getslopes) return min(numret, 2); } +DEFINE_ACTION_FUNCTION_NATIVE(_sectortype, nextsectorneighborz, nextsectorneighborzptr) +{ + PARAM_SELF_STRUCT_PROLOGUE(sectortype); + PARAM_FLOAT(z); + PARAM_INT(find); + ACTION_RETURN_POINTER(nextsectorneighborzptr(self, z, find)); +} + + //============================================================================= void wall_setxpan(walltype* wal, double val) diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index a14670d1a..b784b224f 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -37,14 +37,6 @@ BEGIN_DUKE_NS void dojaildoor(); void moveminecart(); -void ballreturn(DDukeActor* spr); -void pinsectorresetdown(sectortype* sect); -int pinsectorresetup(sectortype* sect); -int checkpins(sectortype* sect); -void resetpins(sectortype* sect); -void resetlanepics(void); - - //--------------------------------------------------------------------------- // // @@ -1191,34 +1183,9 @@ void rr_specialstats() tickstat(STAT_CHICKENPLANT); } - DukeStatIterator it(STAT_BOWLING); - while (auto act = it.Next()) - { - if (act->spr.picnum == BOWLINGPINSPOT) - if (act->spr.lotag == 100) - { - auto pst = pinsectorresetup(act->sector()); - if (pst) - { - act->spr.lotag = 0; - if (act->spr.extra == 1) - { - pst = checkpins(act->sector()); - if (!pst) - { - act->spr.extra = 2; - } - } - if (act->spr.extra == 2) - { - act->spr.extra = 0; - resetpins(act->sector()); - } - } - } - } + tickstat(STAT_BOWLING); - it.Reset(STAT_TELEPORT); + DukeStatIterator it(STAT_TELEPORT); while (auto act = it.Next()) { if (act->spr.picnum == RRTELEPORT) @@ -1254,91 +1221,6 @@ void rr_specialstats() // //--------------------------------------------------------------------------- -static int henstand(DDukeActor *actor) -{ - if (actor->spr.picnum == HENSTAND || actor->spr.picnum == HENSTAND + 1) - { - actor->spr.lotag--; - if (actor->spr.lotag == 0) - { - spawn(actor, HEN); - actor->spr.scale.Zero(); - ChangeActorStat(actor, STAT_MISC); - return 1; - } - } - if (actor->sector()->lotag == 900) - actor->vel.X = 0; - if(actor->vel.X != 0) - { - makeitfall(actor); - Collision coll; - movesprite_ex(actor, DVector3(actor->spr.Angles.Yaw.ToVector() * actor->vel.X, actor->vel.Z), CLIPMASK0, coll); - if (coll.type) - { - if (coll.type == kHitWall) - { - DAngle k = coll.hitWall->delta().Angle(); - actor->spr.Angles.Yaw = k * 2 - actor->spr.Angles.Yaw; - } - else if (coll.type == kHitSprite) - { - auto hitact = coll.actor(); - fi.checkhitsprite(actor, hitact); - if (hitact->spr.picnum == HEN) - { - auto ns = spawn(hitact, HENSTAND); - hitact->spr.scale.Zero(); - ChangeActorStat(hitact, STAT_MISC); - if (ns) - { - ns->vel.X = 2; - ns->spr.lotag = 40; - ns->spr.Angles.Yaw = actor->spr.Angles.Yaw; - } - } - } - } - actor->vel.X -= 1/16.; - if(actor->vel.X < 0) actor->vel.X = 0; - actor->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - if (actor->spr.picnum == BOWLINGPIN) - { - actor->spr.cstat |= CSTAT_SPRITE_XFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16)); - actor->spr.cstat |= CSTAT_SPRITE_YFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16)); - if (krand() & 1) - actor->spr.picnum = BOWLINGPIN + 1; - } - else if (actor->spr.picnum == HENSTAND) - { - actor->spr.cstat |= CSTAT_SPRITE_XFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16)); - actor->spr.cstat |= CSTAT_SPRITE_YFLIP & ESpriteFlags::FromInt(int(actor->vel.X * 16)); - if (krand() & 1) - actor->spr.picnum = HENSTAND + 1; - if (actor->vel.X == 0) - return 2;//actor->Destroy(); still needs to run a script but should not do on a deleted object - } - if (actor->spr.picnum == BOWLINGPIN || (actor->spr.picnum == BOWLINGPIN + 1 && actor->vel.X == 0)) - { - return 2;//actor->Destroy(); still needs to run a script but should not do on a deleted object - } - } - else if (actor->sector()->lotag == 900) - { - if (actor->spr.picnum == BOWLINGBALL) - ballreturn(actor); - actor->Destroy(); - return 1; - } - return 0; -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - void moveactors_r(void) { double xx; @@ -1374,34 +1256,6 @@ void moveactors_r(void) } else switch(act->spr.picnum) { - case BOWLINGBALL: - if (act->vel.X != 0) - { - if(!S_CheckSoundPlaying(356)) - S_PlayActorSound(356,act); - } - else - { - spawn(act,BOWLINGBALLSPRITE); - act->Destroy(); - continue; - } - if (act->sector()->lotag == 900) - { - S_StopSound(356, nullptr); - } - [[fallthrough]]; - case BOWLINGPIN: - case BOWLINGPIN+1: - case HENSTAND: - case HENSTAND+1: - { - int todo = henstand(act); - if (todo == 2) deleteafterexecute = true; - if (todo == 1) continue; - break; - } - case EMPTYBIKE: if (!isRRRA()) break; makeitfall(act); @@ -2175,7 +2029,7 @@ static int fallspecial(DDukeActor *actor, int playernum) } if (actor->sector()->lotag == 800) { - if (actor->spr.picnum == 40) + if (actor->spr.picnum == AMMO) { addspritetodelete(); return 0; diff --git a/source/games/duke/src/bowling.cpp b/source/games/duke/src/bowling.cpp index a45ce8fb4..a8ee2efbe 100644 --- a/source/games/duke/src/bowling.cpp +++ b/source/games/duke/src/bowling.cpp @@ -34,275 +34,29 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms BEGIN_DUKE_NS -void ballreturn(DDukeActor *ball) +void updatepindisplay(int tag, int pins) { - DukeStatIterator it(STAT_BOWLING); - while (auto act = it.Next()) + static const uint8_t pinx[] = { 64, 56, 72, 48, 64, 80, 40, 56, 72, 88 }; + static const uint8_t piny[] = { 48, 40, 40, 32, 32, 32, 24, 24, 24, 24 }; + + if (tag < 1 || tag > 4) return; + tag += BOWLINGLANE1 - 1; + if (TileFiles.tileMakeWritable(tag)) { - if (act->spr.picnum == RRTILE281 && ball->sector() == act->sector()) - { - DukeStatIterator it2(STAT_BOWLING); - while (auto act2 = it2.Next()) - { - if (act2->spr.picnum == BOWLINGBALLSPOT && act->spr.hitag == act2->spr.hitag) - spawn(act2, BOWLINGBALLSPRITE); - if (act2->spr.picnum == BOWLINGPINSPOT && act->spr.hitag == act2->spr.hitag && act2->spr.lotag == 0) - { - act2->spr.lotag = 100; - act2->spr.extra++; - pinsectorresetdown(act2->sector()); - } - } - } - } -} - -void pinsectorresetdown(sectortype* sec) -{ - int j = getanimationindex(anim_ceilingz, sec); - - if (j == -1) - { - setanimation(sec, anim_ceilingz, sec, sec->floorz, 0.25); - } -} - -int pinsectorresetup(sectortype* sec) -{ - int j = getanimationindex(anim_ceilingz, sec); - - if (j == -1) - { - double z = nextsectorneighborzptr(sec, sec->ceilingz, Find_CeilingUp | Find_Safe)->ceilingz; - setanimation(sec, anim_ceilingz, sec, z, 0.25); - return 1; - } - return 0; -} - -int checkpins(sectortype* sect) -{ - int x, y; - bool pins[10] = {}; - int tag = 0; - int pin = 0; - - DukeSectIterator it(sect); - while (auto a2 = it.Next()) - { - if (a2->spr.picnum == BOWLINGPIN) - { - pin++; - pins[a2->spr.lotag] = true; - } - if (a2->spr.picnum == BOWLINGPINSPOT) - { - tag = a2->spr.hitag; - } - } - - if (tag) - { - tag += LANEPICS + 1; - TileFiles.tileMakeWritable(tag); - tileCopySection(LANEPICS + 1, 0, 0, 128, 64, tag, 0, 0); - for (int i = 0; i < 10; i++) - { - if (pins[i]) - { - switch (i) - { - default: - case 0: - x = 64; - y = 48; - break; - case 1: - x = 56; - y = 40; - break; - case 2: - x = 72; - y = 40; - break; - case 3: - x = 48; - y = 32; - break; - case 4: - x = 64; - y = 32; - break; - case 5: - x = 80; - y = 32; - break; - case 6: - x = 40; - y = 24; - break; - case 7: - x = 56; - y = 24; - break; - case 8: - x = 72; - y = 24; - break; - case 9: - x = 88; - y = 24; - break; - } - tileCopySection(LANEPICS, 0, 0, 8, 8, tag, x - 4, y - 10); - } - } - } - - return pin; -} - -void resetpins(sectortype* sect) -{ - int i, tag = 0; - int x, y; - DukeSectIterator it(sect); - while (auto a2 = it.Next()) - { - if (a2->spr.picnum == BOWLINGPIN) - a2->Destroy(); - } - it.Reset(sect); - while (auto a2 = it.Next()) - { - if (a2->spr.picnum == 283) - { - auto spawned = spawn(a2, BOWLINGPIN); - if (spawned) - { - spawned->spr.lotag = a2->spr.lotag; - spawned->clipdist = 12; // random formula here was bogus and always produced 48. - spawned->spr.Angles.Yaw -= DAngle22_5 * 0.125 * (((krand() & 32) - (krand() & 64)) >> 5); // weird formula to preserve number of krand calls. - } - } - if (a2->spr.picnum == 280) - tag = a2->spr.hitag; - } - if (tag) - { - tag += LANEPICS + 1; - TileFiles.tileMakeWritable(tag); - tileCopySection(LANEPICS + 1, 0, 0, 128, 64, tag, 0, 0); - for (i = 0; i < 10; i++) - { - switch (i) - { - default: - case 0: - x = 64; - y = 48; - break; - case 1: - x = 56; - y = 40; - break; - case 2: - x = 72; - y = 40; - break; - case 3: - x = 48; - y = 32; - break; - case 4: - x = 64; - y = 32; - break; - case 5: - x = 80; - y = 32; - break; - case 6: - x = 40; - y = 24; - break; - case 7: - x = 56; - y = 24; - break; - case 8: - x = 72; - y = 24; - break; - case 9: - x = 88; - y = 24; - break; - } - tileCopySection(LANEPICS, 0, 0, 8, 8, tag, x - 4, y - 10); - } + tileCopySection(LANEPICBG, 0, 0, 128, 64, tag, 0, 0); + for (int i = 0; i < 10; i++) if (pins & (1 << i)) + tileCopySection(LANEPICS, 0, 0, 8, 8, tag, pinx[i] - 4, piny[i] - 10); } } void resetlanepics(void) { if (!isRR()) return; - int x, y; for (int tag = 0; tag < 4; tag++) { int pic = tag + 1; if (pic == 0) continue; - pic += LANEPICS + 1; - TileFiles.tileMakeWritable(pic); - tileCopySection(LANEPICS + 1, 0, 0, 128, 64, pic, 0, 0); - for (int i = 0; i < 10; i++) - { - switch (i) - { - default: - case 0: - x = 64; - y = 48; - break; - case 1: - x = 56; - y = 40; - break; - case 2: - x = 72; - y = 40; - break; - case 3: - x = 48; - y = 32; - break; - case 4: - x = 64; - y = 32; - break; - case 5: - x = 80; - y = 32; - break; - case 6: - x = 40; - y = 24; - break; - case 7: - x = 56; - y = 24; - break; - case 8: - x = 72; - y = 24; - break; - case 9: - x = 88; - y = 24; - break; - } - tileCopySection(LANEPICS, 0, 0, 8, 8, pic, x - 4, y - 10); - } + updatepindisplay(pic, 0xffff); } } diff --git a/source/games/duke/src/hudweapon_r.cpp b/source/games/duke/src/hudweapon_r.cpp index 6bd30438d..2aa3a6358 100644 --- a/source/games/duke/src/hudweapon_r.cpp +++ b/source/games/duke/src/hudweapon_r.cpp @@ -351,7 +351,7 @@ void displayweapon_r(int snum, double interpfrac) if (p->ammo_amount[BOWLING_WEAPON]) { hud_drawpal(weapon_xoffset + 162 - look_anghalf, - looking_arc + 214 - gun_pos + (*kb << 3), BOWLINGBALLH, shade, o, pal); + looking_arc + 214 - gun_pos + (*kb << 3), BOWLINGBALLHUD, shade, o, pal); } else { diff --git a/source/games/duke/src/namelist_r.h b/source/games/duke/src/namelist_r.h index 8544141e2..cdefcd9ff 100644 --- a/source/games/duke/src/namelist_r.h +++ b/source/games/duke/src/namelist_r.h @@ -173,10 +173,10 @@ x(WALLLIGHTBUST2, 249) x(LIGHTSWITCH2, 250) x(LIGHTSWITCH2ON, 251) x(UFOBEAM, 252) -y(BOWLINGPINSPOT, 280) -y(RRTILE281, 281) +y(BOWLINGPINCTRL, 280) +y(BOWLINGSECTORLINK, 281) y(BOWLINGBALLSPOT, 282) -y(RRTILE283, 283) +y(BOWLINGPINSPOT, 283) x(CHICKENASPAWN, 285) x(CHICKENCSPAWN, 286) x(FEATHERSPAWN, 287) @@ -664,10 +664,11 @@ y(RRTILE2005, 2005) x(POPCORN, 2021) y(RRTILE2022, 2022) x(LANEPICS, 2023) -y(RRTILE2025, 2025) -y(RRTILE2026, 2026) -y(RRTILE2027, 2027) -y(RRTILE2028, 2028) +x(LANEPICBG, 2024) +x(BOWLINGLANE1, 2025) +x(BOWLINGLANE2, 2026) +x(BOWLINGLANE3, 2027) +x(BOWLINGLANE4, 2028) y(RRTILE2034, 2034) y(RRTILE2050, 2050) y(RRTILE2052, 2052) @@ -1014,11 +1015,12 @@ x(FIRELASER3, 3422) x(FIRELASER4, 3423) x(FIRELASER5, 3424) x(FIRELASER6, 3425) -x(BOWLINGBALLH, 3428) +x(BOWLINGBALLHUD, 3428) x(BOWLINGBALL, 3430) x(BOWLINGBALLSPRITE, 3437) x(POWDERH, 3438) x(BOWLINGPIN, 3440) +x(BOWLINGPIN1, 3441) x(DEVISTATOR, 3445) x(RPGGUN, 3452) y(RRTILE3462, 3462) @@ -1452,6 +1454,7 @@ x(SBDIE, 4820) x(HEN, 4861) x(HENSTAYPUT, 4862) x(HENSTAND, 4897) +x(HENSTAND1, 4898) x(PIG, 4945) x(PIGSTAYPUT, 4946) x(PIGEAT, 4983) diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 7e334fb7b..dbc495fdc 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -838,17 +838,6 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls) } break; } - case BOWLINGBALL: - { - auto j = spawn(actor, atwith); - if (j) - { - j->vel.X = 250 / 16.; - j->spr.Angles.Yaw = actor->spr.Angles.Yaw; - j->spr.pos.Z -= 15; - } - break; - } case OWHIP: case UWHIP: shootwhip(actor, p, spos, sang, atwith); diff --git a/source/games/duke/src/sectors_r.cpp b/source/games/duke/src/sectors_r.cpp index 141bb209e..a923f63f0 100644 --- a/source/games/duke/src/sectors_r.cpp +++ b/source/games/duke/src/sectors_r.cpp @@ -1448,40 +1448,6 @@ void checkhitsprite_r(DDukeActor* targ, DDukeActor* proj) if (spawned) spawned->spriteextra = Scrap6 + (krand() & 15); } break; - case BOWLINGBALL: - proj->vel.X = targ->vel.X * 0.75; - if (krand() & 16) proj->spr.Angles.Yaw -= DAngle22_5 / 8; - S_PlayActorSound(355, targ); - break; - - case BOWLINGPIN: - case BOWLINGPIN + 1: - case HENSTAND: - case HENSTAND + 1: - if (proj->spr.picnum == BOWLINGPIN || proj->spr.picnum == BOWLINGPIN + 1) - { - proj->vel.X *= 0.75; - proj->spr.Angles.Yaw -= targ->spr.Angles.Yaw * 2 + randomAngle(11.25); - targ->spr.Angles.Yaw += randomAngle(22.5 / 8); - S_PlayActorSound(355, targ); - } - else if (proj->spr.picnum == HENSTAND || proj->spr.picnum == HENSTAND + 1) - { - proj->vel.X *= 0.75; - proj->spr.Angles.Yaw -= targ->spr.Angles.Yaw * 2 + randomAngle(22.5 / 8); - targ->spr.Angles.Yaw += randomAngle(22.5 / 8); - S_PlayActorSound(355, targ); - } - else - { - if (krand() & 3) - { - targ->vel.X = 10.25; - targ->spr.Angles.Yaw = proj->spr.Angles.Yaw; - } - } - break; - case FANSPRITE: targ->spr.picnum = FANSPRITEBROKE; targ->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; diff --git a/source/games/duke/src/spawn_r.cpp b/source/games/duke/src/spawn_r.cpp index 236ba83b9..57c4b12cc 100644 --- a/source/games/duke/src/spawn_r.cpp +++ b/source/games/duke/src/spawn_r.cpp @@ -56,21 +56,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* default_case: spawninitdefault(actj, act); break; - case BOWLINGPINSPOT: - case RRTILE281: - case BOWLINGBALLSPOT: - case RRTILE283: - case RRTILE2025: - case RRTILE2026: - case RRTILE2027: - case RRTILE2028: - act->spr.cstat = 0; - act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; - act->spr.scale = DVector2(0, 0); - act->clipdist = 0; - act->spr.extra = 0; - ChangeActorStat(act, STAT_BOWLING); - break; case RRTILE8450: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(1, 1); @@ -172,30 +157,12 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* act->clipdist = 8; ChangeActorStat(act, STAT_ZOMBIEACTOR); break; - case BOWLINGBALL: - act->spr.cstat = CSTAT_SPRITE_BLOCK_HITSCAN; - act->clipdist = 16; - act->spr.scale = DVector2(0.171875, 0.140625); - ChangeActorStat(act, STAT_ZOMBIEACTOR); - break; - case HENSTAND: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 12; - act->spr.scale = DVector2(0.328125, 0.234375); - ChangeActorStat(act, STAT_ZOMBIEACTOR); - break; case RRTELEPORT: case RRTELEPORTDEST: act->spr.scale = DVector2(1, 1); act->clipdist = 16; ChangeActorStat(act, STAT_TELEPORT); break; - case BOWLINGPIN: - act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; - act->clipdist = 12; - act->spr.scale = DVector2(0.359375, 0.359375); - ChangeActorStat(act, STAT_ZOMBIEACTOR); - break; case DUKELYINGDEAD: if (actj && actj->isPlayer()) { @@ -420,7 +387,6 @@ DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* break; case HEN: case HENSTAYPUT: - case HENSTAND: if (act->spr.pal == 35) { act->spr.scale = DVector2(0.65625, 0.46875); diff --git a/source/games/duke/src/vmexports.cpp b/source/games/duke/src/vmexports.cpp index b61c6754c..da0859041 100644 --- a/source/games/duke/src/vmexports.cpp +++ b/source/games/duke/src/vmexports.cpp @@ -30,6 +30,7 @@ int PicForName(int intname) {"DukePigCop", "PIGCOP"}, {"DukeSmallSmoke", "SMALLSMOKE"}, {"DukeBurning", "BURNING"}, + {"RedneckBowlingBallSprite", "BOWLINGBALLSPRITE"}, }; for (auto& p : classes) @@ -176,6 +177,16 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Duke, badguyID, badguypic) ACTION_RETURN_INT(badguypic(p)); } +void updatepindisplay(int tag, int pins); + +DEFINE_ACTION_FUNCTION_NATIVE(_Duke, updatepindisplay, updatepindisplay) +{ + PARAM_PROLOGUE; + PARAM_INT(tag); + PARAM_INT(mask); + updatepindisplay(tag, mask); + return 0; +} DEFINE_GLOBAL_UNSIZED(dlevel) DEFINE_GLOBAL(camsprite) @@ -728,6 +739,13 @@ DEFINE_ACTION_FUNCTION(DDukeActor, attackerflag2) ACTION_RETURN_BOOL(!!attackerflag(self, EDukeFlags2::FromInt(mask))); } +DEFINE_ACTION_FUNCTION(DDukeActor, checktype) // for temporary checking of types that haven't been ported yet. +{ + PARAM_SELF_PROLOGUE(DDukeActor); + PARAM_STRING(name); + ACTION_RETURN_BOOL(self->spr.picnum == TileFiles.tileForName(name)); +} + //--------------------------------------------------------------------------- // @@ -1363,6 +1381,24 @@ DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, LocateTheLocator, LocateTheLocator) ACTION_RETURN_POINTER(LocateTheLocator(tag, sect)); } +DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, getanimationindex, getanimationindex) +{ + PARAM_PROLOGUE; + PARAM_INT(tag); + PARAM_POINTER(sect, sectortype); + ACTION_RETURN_INT(getanimationindex(tag, sect)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_DukeLevel, setanimation, static_cast(setanimation)) +{ + PARAM_PROLOGUE; + PARAM_POINTER(asect, sectortype); + PARAM_INT(tag); + PARAM_POINTER(sect, sectortype); + PARAM_FLOAT(dest); + PARAM_FLOAT(vel); + ACTION_RETURN_INT(setanimation(asect, tag, sect, dest, vel)); +} DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, max_ammo_amount); DEFINE_FIELD_X(DukeGameInfo, DukeGameInfo, playerfriction); diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index 422868e0d..f16fe1fb3 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -132,6 +132,13 @@ spawnclasses 5602 = RedneckCootJibA 5607 = RedneckCootJibB 5616 = RedneckCootJibB + 280 = RedneckBowlingPinController + 281 = RedneckBowlingSectorLink + 282 = RedneckBowlingBallSpot + 283 = RedneckBowlingPinSpot + 3440 = RedneckBowlingPin + 3430 = RedneckBowlingBall + 4897 = RedneckHenstand 3114 = DukeGenericDestructible, "RRTILE3114", "RRTILE3117", "GLASS_BREAKING", spawnglass 2876 = DukeGenericDestructible, "RRTILE2876", "RRTILE2990", "GLASS_BREAKING", spawnglass diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 0a1428d56..dbbe9e76b 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -101,6 +101,7 @@ version "4.10" #include "zscript/games/duke/actors/redneckmisc.zs" +#include "zscript/games/duke/actors/bowling.zs" #include "zscript/games/duke/actors/rabbitspawner.zs" #include "zscript/games/duke/actors/chickenplant.zs" #include "zscript/games/duke/actors/lumberblade.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/bowling.zs b/wadsrc/static/zscript/games/duke/actors/bowling.zs new file mode 100644 index 000000000..ea0b5be6b --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/bowling.zs @@ -0,0 +1,338 @@ +class RedneckBowlingPin : DukeActor +{ + default + { + statnum STAT_ZOMBIEACTOR; + clipdist 12; + scaleX 0.359375; + scaleY 0.359375; + detail 0; + spriteset "BOWLINGPIN", "BOWLINGPIN1"; + } + + override void Initialize() + { + self.cstat |= CSTAT_SPRITE_BLOCK_ALL; + } + + protected void DoTick(int type) + { + if (self.sector.lotag == 900) + self.vel.X = 0; + + if(self.vel.X != 0) + { + self.makeitfall(); + CollisionData coll; + self.movesprite_ex((self.angle.ToVector() * self.vel.X, self.vel.Z), CLIPMASK0, coll); + if (coll.type) + { + if (coll.type == kHitWall) + { + double k = coll.hitWall().delta().Angle(); + self.angle = k * 2 - self.angle; + } + else if (coll.type == kHitSprite) + { + let hitact = DukeActor(coll.hitActor()); + // avoid checkhitsprite here. The way this was handled was just wrong on all accounts + self.collide(hitact); + //if (hitact is "RedneckHen") // does not work yet - Hen is not scriptified. + if (hitact.checkType("HEN")) // Temporary workaround + { + let ns = hitact.spawn("RedneckHenstand"); + hitact.scale = (0,0); + hitact.ChangeStat(STAT_MISC); + if (ns) + { + ns.vel.X = 2; + ns.lotag = 40; + ns.angle = self.angle; + } + } + } + } + self.vel.X -= 1/16.; + if(self.vel.X < 0) self.vel.X = 0; + self.cstat = CSTAT_SPRITE_BLOCK_ALL; + if (type < 2 && self.vel.X > 0) + { + self.cstat |= CSTAT_SPRITE_XFLIP & int(self.vel.X * 16); + self.cstat |= CSTAT_SPRITE_YFLIP & int(self.vel.X * 16); + if (random(0, 1)) self.setSpritesetImage(1); + } + if (type < 2 && self.vel.X == 0) + { + return; + } + } + else if (self.sector.lotag == 900 && type != 2) + { + self.Destroy(); + } + } + + override void Tick() + { + DoTick(0); + } + + + + virtual void collide(DukeActor targa) + { + let targ = RedneckBowlingPin(targa); + if (!targ) return; + + if (targ.detail == 0) + { + self.vel.X *= 0.75; + self.angle -= targ.angle * 2 + frandom(0, 11.25); + targ.angle += frandom(0, 22.5 / 8); + targ.PlayActorSound("BOWLPIN"); + } + else if (targ.detail == 1) + { + self.vel.X *= 0.75; + self.angle -= targ.angle * 2 + frandom(0, 22.5 / 8); + targ.angle += frandom(0, 22.5 / 8); + targ.PlayActorSound("BOWLPIN"); + } + } + + override void onHit(DukeActor hitter) + { + if (random(0, 3)) + { + self.vel.X = 10.25; + self.angle = hitter.angle; + } + } +} + +// chickens on the bowling lane... +class RedneckHenstand : RedneckBowlingPin +{ + default + { + scaleY 0.234375; + spriteset "HENSTAND", "HENSTAND1"; + detail 1; + } + + override void Tick() + { + self.lotag--; + if (self.lotag == 0) + { + self.spawn("RedneckHen"); + self.scale = (0,0); + self.ChangeStat(STAT_MISC); + return; + } + DoTick(1); + } +} + +class RedneckBowlingBall : RedneckBowlingPin +{ + default + { + clipdist 17; + scaleX 0.171875; + scaleY 0.140625; + statnum STAT_ACTOR; + pic "BOWLINGBALL"; + detail 2; + } + + override void Tick() + { + if (self.vel.X != 0) + { + if(!Duke.CheckSoundPlaying("BOWLLOOP")) + self.PlayActorSound("BOWLLOOP"); + } + else + { + self.spawn("RedneckBowlingBallSprite"); + self.Destroy(); + return; + } + if (self.sector.lotag == 900) + { + self.StopSound("BOWLLOOP"); + } + DoTick(2); + if (self.sector.lotag == 900) + { + self.ballreturn(); + self.Destroy(); + return; + } + } + + private void ballreturn() + { + DukeStatIterator it; + for (let act1 = it.First(STAT_BOWLING); act1; act1 = it.Next()) + { + if (act1.getClassName() == 'RedneckBowlingSectorLink' && self.sector == act1.sector) + { + DukeStatIterator it2; + for (let act2 = it2.First(STAT_BOWLING); act2; act2 = it2.Next()) + { + if (act2.getClassName() == 'RedneckBowlingBallSpot' && act1.hitag == act2.hitag) + { + act2.spawn("RedneckBowlingBallSprite"); + } + if (act2.getClassName() == 'RedneckBowlingPinController' && act1.hitag == act2.hitag && act2.lotag == 0) + { + let sec = act2.sector; + act2.lotag = 100; + act2.extra++; + int j = dlevel.getanimationindex(dlevel.anim_ceilingz, sec); + if (j == -1) + dlevel.setanimation(sec, dlevel.anim_ceilingz, sec, sec.floorz, 0.25); + } + } + } + } + } + + override void onHit(DukeActor hitter) + { + } + + override void collide(DukeActor targ) + { + targ.vel.X = self.vel.X * 0.75; + if (random(0, 32767) & 16) targ.angle -= 22.5 / 8; + targ.PlayActorSound("BOWLPIN"); + } + + override bool ShootThis(DukeActor actor, DukePlayer plr, Vector3 spos, double sang) + { + let j = actor.spawn(self.GetClassName()); + if (j) + { + j.vel.X = 250 / 16.; + j.angle = self.angle; + j.pos.Z -= 15; + } + return true; + } +} + +class RedneckBowlingController : DukeActor +{ + default + { + statnum STAT_BOWLING; + scaleX 0; + scaleY 0; + clipdist 0; + extra 0; + } + + override void Initialize() + { + self.cstat = CSTAT_SPRITE_INVISIBLE; + } +} + +class RedneckBowlingPinController : RedneckBowlingController +{ + override void Tick() + { + if (self.lotag == 100) + { + let pst = pinsectorresetup(); + if (pst) + { + self.lotag = 0; + if (self.extra == 1) + { + pst = checkpins(); + if (!pst) + { + self.extra = 2; + } + } + if (self.extra == 2) + { + self.extra = 0; + resetpins(); + } + } + } + } + + int pinsectorresetup() + { + let sec = self.sector; + int j = dlevel.getanimationindex(dlevel.anim_ceilingz, sec); + + if (j == -1) + { + double z = sec.nextsectorneighborz(sec.ceilingz, sectortype.Find_CeilingUp | sectortype.Find_Safe).ceilingz; + dlevel.setanimation(sec, dlevel.anim_ceilingz, sec, z, 0.25); + return 1; + } + return 0; + } + + int checkpins() + { + int pins = 0; + int pin = 0; + + DukeSectIterator it; + for (let a2 = it.First(self.sector); a2; a2 = it.Next()) + { + if (a2.GetClassName() == 'RedneckBowlingPin' && a2.spritesetindex == 0) + { + pin++; + pins |= 1 << a2.lotag; + } + } + + Duke.updatepindisplay(self.hitag, pins); + return pin; + } + + void resetpins() + { + int i, tag = 0; + DukeSectIterator it; + for (let a2 = it.First(self.sector); a2; a2 = it.Next()) + { + if (a2.GetClassName() == 'RedneckBowlingPin') + a2.Destroy(); + } + for (let a2 = it.First(self.sector); a2; a2 = it.Next()) + { + if (a2.GetClassName() == 'RedneckBowlingPinSpot') + { + let spawned = a2.spawn('RedneckBowlingPin'); + if (spawned) + { + spawned.lotag = a2.lotag; + spawned.clipdist = 12; // random formula here was bogus and always produced 48. + spawned.angle -= 22.5 * 0.125 * (((random(0, 32767) & 32) - (random(0, 32767) & 64)) >> 5); + } + } + } + Duke.updatepindisplay(self.hitag, 0xffff); + } +} + +class RedneckBowlingSectorLink : RedneckBowlingController +{ } + +class RedneckBowlingBallSpot : RedneckBowlingController +{ } + +class RedneckBowlingPinSpot : RedneckBowlingController +{ } + diff --git a/wadsrc/static/zscript/games/duke/actors/queball.zs b/wadsrc/static/zscript/games/duke/actors/queball.zs index 3475e92a6..3b275b1c7 100644 --- a/wadsrc/static/zscript/games/duke/actors/queball.zs +++ b/wadsrc/static/zscript/games/duke/actors/queball.zs @@ -44,7 +44,10 @@ class DukeQueball : DukeActor } else if (j == kHitSprite) { - self.checkhitsprite(DukeActor(colli.hitactor())); + // the logic here was inverted, so to set things right the type check had to be added. + let targ = DukeActor(colli.hitactor()); + if (targ is 'DukeQueball') + targ.checkhitsprite(self); } self.vel.X -= 1/16.; @@ -108,10 +111,10 @@ class DukeQueball : DukeActor { if (hitter is 'DukeQueball') { - hitter.vel.X = self.vel.X * 0.75; - hitter.angle -= Normalize180(self.angle) * 2 + 180; - self.angle = (self.pos.XY - hitter.pos.XY).Angle() - 90; - self.PlayActorSound("POOLBALLHIT"); + self.vel.X = hitter.vel.X * 0.75; + self.angle -= Normalize180(hitter.angle) * 2 + 180; + hitter.angle = (hitter.pos.XY - self.pos.XY).Angle() - 90; + hitter.PlayActorSound("POOLBALLHIT"); } else { diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index 6b61283b3..f970587a7 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -225,6 +225,7 @@ class DukeActor : CoreActor native native int actorflag3(int mask); native int attackerflag1(int mask); native int attackerflag2(int mask); + 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) @@ -288,6 +289,14 @@ extend struct _ // On the script side we do not really want scattered global data that is publicly accessible. struct DukeLevel { + enum animtype_t + { + anim_floorz, + anim_ceilingz, + anim_vertexx, + anim_vertexy, + }; + native DukeActor SpawnActor(sectortype sect, Vector3 pos, class type, int shade, Vector2 scale, double angle, double vel, double zvel, DukeActor owner, int stat = -1); native static int check_activator_motion(int lotag); native static void operatemasterswitches(int lotag); @@ -304,6 +313,8 @@ struct DukeLevel native static void checkhitwall(walltype wal, DukeActor hitter, Vector3 hitpos); native static void checkhitceiling(sectortype wal, DukeActor hitter); native static DukeActor LocateTheLocator(int n, sectortype sect); + native static int getanimationindex(int type, sectortype sec); + native static int setanimation(sectortype animsect, int type, sectortype sec, double target, double vel); } struct DukeStatIterator diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs index 9742d1d4f..aa6aee38b 100644 --- a/wadsrc/static/zscript/games/duke/dukegame.zs +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -153,6 +153,7 @@ struct Duke native native static int global_random(); native static int GetSoundFlags(Sound snd); native static int badguyID(int id); + native static void updatepindisplay(int tag, int pinmask); static int rnd(int val) { return (random(0, 255) >= (255 - (val))); diff --git a/wadsrc/static/zscript/maptypes.zs b/wadsrc/static/zscript/maptypes.zs index e831e6929..bc80ec8b7 100644 --- a/wadsrc/static/zscript/maptypes.zs +++ b/wadsrc/static/zscript/maptypes.zs @@ -118,6 +118,22 @@ enum ESectorExBits struct sectortype native { + enum EFindNextSector + { + Find_Floor = 0, + Find_Ceiling = 1, + + Find_Down = 0, + Find_Up = 2, + + Find_Safe = 4, + + Find_CeilingUp = Find_Ceiling | Find_Up, + Find_CeilingDown = Find_Ceiling | Find_Down, + Find_FloorUp = Find_Floor | Find_Up, + Find_FloorDown = Find_Floor | Find_Down, + }; + // panning byte fields were promoted to full floats to enable panning interpolation. native readonly float ceilingxpan; native readonly float ceilingypan; @@ -218,6 +234,8 @@ struct sectortype native native int ceilingslope(); native int floorslope(); native double, double getslopes(Vector2 pos); + native sectortype nextsectorneighborz(double refz, int find); + } //=============================================================================