//------------------------------------------------------------------------- /* Copyright (C) 1996, 2003 - 3D Realms Entertainment Copyright (C) 2017-2019 Nuke.YKT Copyright (C) 2020 - Christoph Oelckers This file is part of Duke Nukem 3D version 1.5 - Atomic Edition Duke Nukem 3D is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Original Source: 1996 - Todd Replogle Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms */ //------------------------------------------------------------------------- #include #include "ns.h" #include "global.h" #include "sounds.h" #include "names_r.h" #include "dukeactor.h" BEGIN_DUKE_NS DDukeActor* spawninit_r(DDukeActor* actj, DDukeActor* act, TArray* actors) { if (actorflag(act, SFLAG2_TRIGGERRESPAWN)) { act->spr.yint = act->spr.hitag; act->spr.hitag = -1; } if (iseffector(act)) { spawneffector(act, actors); return act; } if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { if (spawninitdefault(actj, act)) CallInitialize(act); return act; } auto sectp = act->sector(); switch (act->spr.picnum) { default: default_case: spawninitdefault(actj, act); break; case RTILE_RRTILE7936: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0, 0); fogactive = 1; break; case RTILE_RRTILE6144: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0, 0); ps[screenpeek].sea_sick_stat = 1; break; case RTILE_RRTILE8193: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0, 0); pistonsound = 1; break; case RTILE_TRANSPORTERSTAR: case RTILE_TRANSPORTERBEAM: spawntransporter(actj, act, act->spr.picnum == RTILE_TRANSPORTERBEAM); break; case RTILE_BLOOD: act->spr.scale = DVector2(0.0625, 0.0625); act->spr.pos.Z -= 26; ChangeActorStat(act, STAT_MISC); break; case RTILE_GRATE1: act->clipdist = 8; act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; ChangeActorStat(act, 0); break; case RTILE_FEM10: case RTILE_NAKED1: case RTILE_STATUE: case RTILE_TOUGHGAL: act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; act->clipdist = 8; ChangeActorStat(act, STAT_ZOMBIEACTOR); break; case RTILE_DUKELYINGDEAD: if (actj && actj->isPlayer()) { act->spr.scale = actj->spr.scale; act->spr.shade = actj->spr.shade; act->spr.pal = ps[actj->PlayerIndex()].palookup; } act->spr.cstat = 0; act->spr.extra = 1; act->vel.X = 292 / 16.; act->vel.Z = 360 / 256.; act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; act->clipdist = 32; [[fallthrough]]; case RTILE_MIKE: if (act->spr.picnum == RTILE_MIKE) act->spr.yint = act->spr.hitag; ChangeActorStat(act, STAT_ACTOR); break; case RTILE_EXPLOSION2: case RTILE_EXPLOSION3: case RTILE_BURNING: case RTILE_SMALLSMOKE: if (actj) { act->spr.Angles.Yaw = actj->spr.Angles.Yaw; act->spr.shade = -64; act->spr.cstat = CSTAT_SPRITE_YCENTER | randomXFlip(); } if (act->spr.picnum == RTILE_EXPLOSION2) { act->spr.scale = DVector2(0.75, 0.75); act->spr.shade = -127; act->spr.cstat |= CSTAT_SPRITE_YCENTER; } else if (act->spr.picnum == RTILE_EXPLOSION3) { act->spr.scale = DVector2(2, 2); act->spr.shade = -127; act->spr.cstat |= CSTAT_SPRITE_YCENTER; } else if (act->spr.picnum == RTILE_SMALLSMOKE) { act->spr.scale = DVector2(0.1875, 0.1875); } else if (act->spr.picnum == RTILE_BURNING) { act->spr.scale = DVector2(0.0625, 0.0625); } if (actj) { double x = getflorzofslopeptr(act->sector(), act->spr.pos); if (act->spr.pos.Z > x - 12) act->spr.pos.Z = x - 12; } ChangeActorStat(act, STAT_MISC); break; case RTILE_PLAYERONWATER: if (actj) { act->spr.scale = actj->spr.scale; act->vel.Z = 0.5; if (act->sector()->lotag != 2) act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; } ChangeActorStat(act, STAT_DUMMYPLAYER); break; case RTILE_APLAYER: { act->spr.scale = DVector2(0, 0); int j = ud.coop; if (j == 2) j = 0; if (ud.multimode < 2 || (ud.multimode > 1 && j != act->spr.lotag)) ChangeActorStat(act, STAT_MISC); else ChangeActorStat(act, STAT_PLAYER); break; } case RTILE_WATERBUBBLE: if (actj && actj->isPlayer()) act->spr.pos.Z -= 16; if (act->spr.picnum == RTILE_WATERBUBBLE) { if (actj) act->spr.Angles.Yaw = actj->spr.Angles.Yaw; double s = REPEAT_SCALE + (krand() & 7) * REPEAT_SCALE; act->spr.scale = DVector2(s, s); } else act->spr.scale = DVector2(0.5, 0.5); ChangeActorStat(act, STAT_MISC); break; case RTILE_WATERBUBBLEMAKER: act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; ChangeActorStat(act, STAT_STANDABLE); break; // this is not really nice... case RTILE_BIKERB: case RTILE_BIKERBV2: case RTILE_BIKER: case RTILE_MAKEOUT: case RTILE_CHEERB: case RTILE_CHEER: case RTILE_COOTPLAY: case RTILE_BILLYPLAY: case RTILE_MINIONBOAT: case RTILE_HULKBOAT: case RTILE_CHEERBOAT: case RTILE_RABBIT: case RTILE_ROCK: case RTILE_ROCK2: case RTILE_MAMACLOUD: case RTILE_MAMA: if (isRRRA()) goto rrra_badguy2; else goto default_case; case RTILE_SBSWIPE: case RTILE_CHEERSTAYPUT: if (isRRRA()) goto rrra_stayput; else goto default_case; case RTILE_SBMOVE: if (isRRRA()) goto default_case; [[fallthrough]]; case RTILE_BILLYRAYSTAYPUT: case RTILE_BRAYSNIPER: case RTILE_BUBBASTAND: case RTILE_HULKSTAYPUT: case RTILE_HENSTAYPUT: case RTILE_PIGSTAYPUT: case RTILE_MINIONSTAYPUT: case RTILE_COOTSTAYPUT: rrra_stayput: act->actorstayput = act->sector(); [[fallthrough]]; case RTILE_BOULDER: case RTILE_BOULDER1: case RTILE_TORNADO: case RTILE_BILLYCOCK: case RTILE_BILLYRAY: case RTILE_DOGRUN: case RTILE_LTH: case RTILE_HULK: case RTILE_HEN: case RTILE_DRONE: case RTILE_PIG: case RTILE_MINION: case RTILE_COW: case RTILE_COOT: case RTILE_VIXEN: rrra_badguy2: act->spr.scale = DVector2(0.625, 0.625); // Note: All inappropriate tiles have already been weeded out by the outer switch block so this does not need game type checks anymore. switch (act->spr.picnum) { case RTILE_VIXEN: if (act->spr.pal == 34) { act->spr.scale = DVector2(0.34375, 0.328125); } else { act->spr.scale = DVector2(0.34375, 0.3125); } act->setClipDistFromTile(); break; case RTILE_HULKHANG: case RTILE_HULKHANGDEAD: case RTILE_HULKJUMP: case RTILE_HULK: case RTILE_HULKSTAYPUT: act->spr.scale = DVector2(0.5, 0.5); act->setClipDistFromTile(); break; case RTILE_COOTPLAY: case RTILE_COOT: case RTILE_COOTSTAYPUT: act->spr.scale = DVector2(0.375, 0.28125); act->setClipDistFromTile(); act->clipdist *= 4; break; case RTILE_DRONE: act->spr.scale = DVector2(0.21875, 0.109375); act->clipdist = 32; break; case RTILE_SBSWIPE: case RTILE_BILLYPLAY: case RTILE_BILLYCOCK: case RTILE_BILLYRAY: case RTILE_BILLYRAYSTAYPUT: case RTILE_BRAYSNIPER: case RTILE_BUBBASTAND: act->spr.scale = DVector2(0.390625, 0.328125); act->setClipDistFromTile(); break; case RTILE_COW: act->spr.scale = DVector2(0.5, 0.5); act->setClipDistFromTile(); break; case RTILE_HEN: case RTILE_HENSTAYPUT: if (act->spr.pal == 35) { act->spr.scale = DVector2(0.65625, 0.46875); act->setClipDistFromTile(); } else { act->spr.scale = DVector2(0.328125, 0.234375); act->clipdist = 16; } break; case RTILE_MINION: case RTILE_MINIONSTAYPUT: act->spr.scale = DVector2(0.25, 0.25); act->setClipDistFromTile(); if (isRRRA() && ud.ufospawnsminion) act->spr.pal = 8; break; case RTILE_DOGRUN: case RTILE_PIG: act->spr.scale = DVector2(0.25, 0.25); act->setClipDistFromTile(); break; case RTILE_RABBIT: act->spr.scale = DVector2(0.28125, 0.28125); act->setClipDistFromTile(); break; case RTILE_MAMACLOUD: act->spr.scale = DVector2(1, 1); act->spr.cstat = CSTAT_SPRITE_TRANSLUCENT; act->spr.cstat |= CSTAT_SPRITE_TRANS_FLIP; act->spr.pos.X += krandf(128) - 64; act->spr.pos.Y += krandf(128) - 64; act->spr.pos.Z += krandf(8) - 4; break; case RTILE_MAMA: if (actj && isrespawncontroller(actj)) act->spr.pal = actj->spr.pal; if (act->spr.pal == 30) { act->spr.scale = DVector2(0.40625, 0.40625); act->clipdist = 18.75; } else if (act->spr.pal == 31) { act->spr.scale = DVector2(0.5625, 0.5625); act->clipdist = 25; } else if (act->spr.pal == 32) { act->spr.scale = DVector2(0.78125, 0.78125); act->clipdist = 25; } else { act->spr.scale = DVector2(0.78125, 0.78125); act->clipdist = 25; } break; case RTILE_BIKERB: act->spr.scale = DVector2(0.4375, 0.34375); act->clipdist = 18; break; case RTILE_BIKERBV2: act->spr.scale = DVector2(0.4375, 0.34375); act->clipdist = 18; break; case RTILE_BIKER: act->spr.scale = DVector2(0.4375, 0.34375); act->setClipDistFromTile(); break; case RTILE_CHEERB: act->spr.scale = DVector2(0.4375, 0.34375); act->clipdist = 18; break; case RTILE_CHEER: case RTILE_CHEERSTAYPUT: act->spr.scale = DVector2(0.34375, 0.3125); act->setClipDistFromTile(); break; case RTILE_MAKEOUT: act->spr.scale = DVector2(0.40625, 0.40625); act->setClipDistFromTile(); break; case RTILE_MINIONBOAT: act->spr.scale = DVector2(0.25, 0.25); act->setClipDistFromTile(); break; case RTILE_HULKBOAT: act->spr.scale = DVector2(0.75, 0.75); act->setClipDistFromTile(); break; case RTILE_CHEERBOAT: act->spr.scale = DVector2(0.5, 0.5); act->setClipDistFromTile(); break; case RTILE_TORNADO: act->spr.scale = DVector2(1, 2); act->setClipDistFromTile(); act->clipdist *= 0.25; act->spr.cstat = CSTAT_SPRITE_TRANSLUCENT; break; case RTILE_LTH: act->spr.scale = DVector2(0.375, 0.34375); act->setClipDistFromTile(); break; case RTILE_ROCK: case RTILE_ROCK2: act->spr.scale = DVector2(1, 1); act->setClipDistFromTile(); break; case RTILE_SBMOVE: act->spr.scale = DVector2(0.75, 0.75); act->setClipDistFromTile(); break; default: break; } if (actj) act->spr.lotag = 0; if ((act->spr.lotag > ud.player_skill) || ud.monsters_off == 1) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; } else { makeitfall(act); act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; if (act->spr.picnum != 5501) if (actorfella(act)) ps[myconnectindex].max_actors_killed++; if (actj) { act->timetosleep = 0; check_fta_sounds_r(act); ChangeActorStat(act, STAT_ACTOR); act->spr.shade = actj->spr.shade; } else ChangeActorStat(act, STAT_ZOMBIEACTOR); } break; case RTILE_RPG2SPRITE: case RTILE_MOTOAMMO: case RTILE_BOATAMMO: if (!isRRRA()) goto default_case; [[fallthrough]]; case RTILE_ATOMICHEALTH: case RTILE_STEROIDS: case RTILE_HEATSENSOR: case RTILE_SHIELD: case RTILE_AIRTANK: case RTILE_POWDERKEG: case RTILE_COWPIE: case RTILE_HOLODUKE: case RTILE_FIRSTGUNSPRITE: case RTILE_RIFLEGUNSPRITE: case RTILE_SHOTGUNSPRITE: case RTILE_CROSSBOWSPRITE: case RTILE_RIPSAWSPRITE: case RTILE_TITSPRITE: case RTILE_ALIENBLASTERSPRITE: case RTILE_SHOTGUNAMMO: case RTILE_FREEZEAMMO: case RTILE_HBOMBAMMO: case RTILE_CRYSTALAMMO: case RTILE_GROWAMMO: case RTILE_BATTERYAMMO: case RTILE_DEVISTATORAMMO: case RTILE_RPGAMMO: case RTILE_BOOTS: case RTILE_AMMO: case RTILE_AMMOLOTS: case RTILE_BEER: case RTILE_FIRSTAID: case RTILE_SIXPAK: case RTILE_SAWAMMO: case RTILE_BOWLINGBALLSPRITE: if (actj) { act->spr.lotag = 0; if (act->spr.picnum != RTILE_BOWLINGBALLSPRITE) { act->spr.pos.Z -= 32; act->vel.Z = -4; } else { act->vel.Z = 0; } ssp(act, CLIPMASK0); act->spr.cstat = randomXFlip(); } else { act->SetOwner(act); act->spr.cstat = 0; } if ((ud.multimode < 2 && act->spr.pal != 0) || (act->spr.lotag > ud.player_skill)) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; } act->spr.pal = 0; [[fallthrough]]; case RTILE_ACCESSCARD: if (act->spr.picnum == RTILE_ATOMICHEALTH) act->spr.cstat |= CSTAT_SPRITE_YCENTER; if (ud.multimode > 1 && ud.coop != 1 && act->spr.picnum == RTILE_ACCESSCARD) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; } else { if (act->spr.picnum == RTILE_AMMO) act->spr.scale = DVector2(0.25, 0.25); else act->spr.scale = DVector2(0.5, 0.5); } act->spr.shade = -17; if (actj) ChangeActorStat(act, STAT_ACTOR); else { ChangeActorStat(act, STAT_ZOMBIEACTOR); makeitfall(act); } switch (act->spr.picnum) { case RTILE_FIRSTGUNSPRITE: act->spr.scale = DVector2(0.25, 0.25); break; case RTILE_SHOTGUNAMMO: act->spr.scale = DVector2(0.28125, 0.265625); if (isRRRA()) act->spr.cstat = CSTAT_SPRITE_BLOCK_HITSCAN; break; case RTILE_SIXPAK: act->spr.scale = DVector2(0.203125, 0.140625); if (isRRRA()) act->spr.cstat = CSTAT_SPRITE_BLOCK_HITSCAN; break; case RTILE_FIRSTAID: act->spr.scale = DVector2(0.125, 0.125); break; case RTILE_BEER: act->spr.scale = DVector2(0.078125, 0.0625); break; case RTILE_AMMO: act->spr.scale = DVector2(0.140625, 0.140625); break; case RTILE_MOTOAMMO: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0.359375, 0.359375); break; case RTILE_BOATAMMO: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0.25, 0.25); break; case RTILE_COWPIE: act->spr.scale = DVector2(0.125, 0.09375); break; case RTILE_STEROIDS: act->spr.scale = DVector2(0.203125, 0.140625); break; case RTILE_ACCESSCARD: act->spr.scale = DVector2(0.171875, 0.1875); break; case RTILE_HEATSENSOR: act->spr.scale = DVector2(0.09375, 0.0625); break; case RTILE_AIRTANK: act->spr.scale = DVector2(0.296875, 0.25); break; case RTILE_BATTERYAMMO: act->spr.scale = DVector2(0.234375, 0.234375); break; case RTILE_BOWLINGBALLSPRITE: act->spr.scale = DVector2(0.171875, 0.171875); break; case RTILE_POWDERKEG: act->spr.scale = DVector2(0.171875, 0.171875); act->spr.yint = 4; act->vel.X = 2; break; case RTILE_CROSSBOWSPRITE: act->spr.scale = DVector2(0.25, 0.21875); break; case RTILE_RPG2SPRITE: if (!isRRRA()) goto default_case; act->spr.scale = DVector2(0.34375, 0.3125); break; case RTILE_RIPSAWSPRITE: act->spr.scale = DVector2(0.34375, 0.203125); break; case RTILE_ALIENBLASTERSPRITE: act->spr.scale = DVector2(0.28125, 0.265625); break; case RTILE_SAWAMMO: act->spr.scale = DVector2(0.1875, 0.109375); break; case RTILE_GROWSPRITEICON: act->spr.scale = DVector2(0.15625, 0.140625); break; case RTILE_DEVISTATORAMMO: act->spr.scale = DVector2(0.15625, 0.140625); break; case RTILE_ATOMICHEALTH: act->spr.scale = DVector2(0.125, 0.125); break; case RTILE_TITSPRITE: act->spr.scale = DVector2(0.265625, 0.25); break; } act->spr.shade = act->sector()->floorshade; break; case RTILE_STEAM: if (actj) { act->spr.Angles.Yaw = actj->spr.Angles.Yaw; act->spr.cstat = CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_TRANSLUCENT; act->spr.scale = DVector2(REPEAT_SCALE, REPEAT_SCALE); act->vel.X = -0.5; ssp(act, CLIPMASK0); } [[fallthrough]]; case RTILE_CEILINGSTEAM: ChangeActorStat(act, STAT_STANDABLE); break; case RTILE_RUBBERCAN: act->spr.extra = 0; [[fallthrough]]; case RTILE_EXPLODINGBARREL: case RTILE_HORSEONSIDE: case RTILE_FIREBARREL: case RTILE_NUKEBARREL: case RTILE_FIREVASE: case RTILE_NUKEBARRELDENTED: case RTILE_NUKEBARRELLEAKED: case RTILE_WOODENHORSE: if (actj) act->spr.scale = DVector2(0.5, 0.5); act->clipdist = 18; makeitfall(act); if (actj) act->SetOwner(actj); else act->SetOwner(act); [[fallthrough]]; case RTILE_EGG: if (ud.monsters_off == 1 && act->spr.picnum == RTILE_EGG) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); } else { if (act->spr.picnum == RTILE_EGG) act->clipdist = 6; act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL | randomXFlip(); ChangeActorStat(act, STAT_ZOMBIEACTOR); } break; case RTILE_TOILETWATER: act->spr.shade = -16; ChangeActorStat(act, STAT_STANDABLE); break; case RTILE_RRTILE63: act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; act->spr.scale = DVector2(REPEAT_SCALE, REPEAT_SCALE); act->clipdist = 0.25; ChangeActorStat(act, 100); break; } return act; } END_DUKE_NS