//------------------------------------------------------------------------- /* Copyright (C) 1996, 2003 - 3D Realms Entertainment Copyright (C) 2000, 2003 - Matt Saettler (EDuke Enhancements) Copyright (C) 2020 - Christoph Oelckers This file is part of Enhanced 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 EDuke enhancements integrated: 04/13/2003 - Matt Saettler Note: EDuke source was in transition. Changes are in-progress in the source as it is released. */ //------------------------------------------------------------------------- #include #include "ns.h" #include "global.h" #include "sounds.h" #include "names_d.h" #include "dukeactor.h" BEGIN_DUKE_NS DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray* actors) { if (actorflag(act, SFLAG2_TRIGGERRESPAWN)) { act->spr.yint = act->spr.hitag; act->spr.hitag = -1; } if (iseffector(act)) { // for in-game spawned SE's the init code must not run. The only type ever being spawned that way is SE128 - // but we cannot check that here as the number has not been set yet. if (actj == 0) spawneffector(act, actors); return act; } if (act->GetClass() != RUNTIME_CLASS(DDukeActor)) { if (!badguy(act) || commonEnemySetup(act, actj)) CallInitialize(act); return act; } auto sectp = act->sector(); if (isWorldTour()) { switch (act->spr.picnum) { case DTILE_BOSS2STAYPUT: case DTILE_BOSS3STAYPUT: case DTILE_BOSS5STAYPUT: act->actorstayput = act->sector(); [[fallthrough]]; case DTILE_FIREFLY: case DTILE_BOSS5: if (act->spr.picnum != DTILE_FIREFLY) { if (actj && isrespawncontroller(actj)) act->spr.pal = actj->spr.pal; if (act->spr.pal != 0) { act->clipdist = 20; act->spr.scale = DVector2(0.625, 0.625); } else { act->spr.scale = DVector2(1.25, 1.25); act->clipdist = 41; } } else { act->spr.scale = DVector2(0.625, 0.625); act->clipdist = 20; } if (actj) act->spr.lotag = 0; if ((act->spr.lotag > ud.player_skill) || ud.monsters_off) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; } else { makeitfall(act); act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; ps[connecthead].max_actors_killed++; if (actj) { act->timetosleep = 0; check_fta_sounds_d(act); ChangeActorStat(act, STAT_ACTOR); } else ChangeActorStat(act, STAT_ZOMBIEACTOR); } return act; case DTILE_WHISPYSMOKE: ChangeActorStat(act, STAT_MISC); act->spr.pos.X += krandf(16) - 8; act->spr.pos.Y += krandf(16) - 8; act->spr.scale = DVector2(0.3125, 0.3125); return act; case DTILE_SERIOUSSAM: ChangeActorStat(act, STAT_ZOMBIEACTOR); act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL; act->spr.extra = 150; return act; } } switch (act->spr.picnum) { default: if (!badguy(act) || commonEnemySetup(act, actj)) CallInitialize(act); break; case FOF: act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; case DTILE_BLOOD: act->spr.scale = DVector2(0.25, 0.25); act->spr.pos.Z -= 26; if (actj && actj->spr.pal == 6) act->spr.pal = 6; ChangeActorStat(act, STAT_MISC); break; case DTILE_FECES: if (actj) act->spr.scale = DVector2(REPEAT_SCALE, REPEAT_SCALE); ChangeActorStat(act, STAT_MISC); break; case DTILE_FEM1: case DTILE_FEM2: case DTILE_FEM3: case DTILE_FEM4: case DTILE_FEM5: case DTILE_FEM6: case DTILE_FEM7: case DTILE_FEM8: case DTILE_FEM9: case DTILE_FEM10: case DTILE_PODFEM1: case DTILE_NAKED1: case DTILE_TOUGHGAL: if (act->spr.picnum == DTILE_PODFEM1) act->spr.extra <<= 1; [[fallthrough]]; case DTILE_BLOODYPOLE: act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; act->clipdist = 8; ChangeActorStat(act, STAT_ZOMBIEACTOR); break; case DTILE_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.; [[fallthrough]]; case DTILE_BLIMP: act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL; act->clipdist = 32; [[fallthrough]]; case DTILE_MIKE: if (act->spr.picnum == DTILE_MIKE) act->spr.yint = act->spr.hitag; ChangeActorStat(act, 1); break; case DTILE_ONFIRE: // Twentieth Anniversary World Tour if (!isWorldTour()) break; [[fallthrough]]; case DTILE_SMALLSMOKE: if (actj) { act->spr.Angles.Yaw = actj->spr.Angles.Yaw; act->spr.shade = -64; act->spr.cstat = CSTAT_SPRITE_YCENTER | randomXFlip(); } act->spr.scale = DVector2(0.375, 0.375); if (actj) { double x = getflorzofslopeptr(act->sector(), act->spr.pos); if (act->spr.pos.Z > x - 12) act->spr.pos.Z = x - 12; } if (act->spr.picnum == DTILE_ONFIRE) { act->spr.pos.X += krandf(32) - 16; act->spr.pos.Y += krandf(32) - 16; act->spr.pos.Z -= krandf(40); act->spr.cstat |= CSTAT_SPRITE_YCENTER; } ChangeActorStat(act, STAT_MISC); break; case DTILE_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 DTILE_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 DTILE_WATERDRIPSPLASH: // ok act->spr.scale = DVector2(0.375, 0.375); ChangeActorStat(act, STAT_STANDABLE); break; case DTILE_WATERBUBBLEMAKER: if (act->spr.hitag && act->spr.picnum == DTILE_WATERBUBBLEMAKER) { // JBF 20030913: Pisses off move(), eg. in bobsp2 Printf(TEXTCOLOR_YELLOW "WARNING: DTILE_WATERBUBBLEMAKER %d @ %d,%d with hitag!=0. Applying fixup.\n", act->GetIndex(), int(act->spr.pos.X), int(act->spr.pos.Y)); act->spr.hitag = 0; } act->spr.cstat |= CSTAT_SPRITE_INVISIBLE; ChangeActorStat(act, STAT_STANDABLE); break; case DTILE_OCTABRAINSTAYPUT: case DTILE_LIZTROOPSTAYPUT: case DTILE_LIZMANSTAYPUT: case DTILE_BOSS1STAYPUT: case DTILE_COMMANDERSTAYPUT: case DTILE_BOSS4STAYPUT: act->actorstayput = act->sector(); [[fallthrough]]; case DTILE_BOSS1: case DTILE_BOSS2: case DTILE_BOSS3: case DTILE_BOSS4: case DTILE_ROTATEGUN: case DTILE_DRONE: case DTILE_LIZTROOPONTOILET: case DTILE_LIZTROOPJUSTSIT: case DTILE_LIZTROOPSHOOT: case DTILE_LIZTROOPJETPACK: case DTILE_LIZTROOPDUCKING: case DTILE_LIZTROOPRUNNING: case DTILE_LIZTROOP: case DTILE_OCTABRAIN: case DTILE_COMMANDER: case DTILE_LIZMAN: case DTILE_LIZMANSPITTING: case DTILE_LIZMANFEEDING: case DTILE_LIZMANJUMP: case DTILE_ORGANTIC: case DTILE_SHARK: if (act->spr.pal == 0) { switch (act->spr.picnum) { case DTILE_LIZTROOPONTOILET: case DTILE_LIZTROOPSHOOT: case DTILE_LIZTROOPJETPACK: case DTILE_LIZTROOPDUCKING: case DTILE_LIZTROOPRUNNING: case DTILE_LIZTROOPSTAYPUT: case DTILE_LIZTROOPJUSTSIT: case DTILE_LIZTROOP: act->spr.pal = 22; break; } } if (bossguy(act)) { if (actj && isrespawncontroller(actj)) act->spr.pal = actj->spr.pal; if (act->spr.pal && (!isWorldTour() || !(currentLevel->flags & LEVEL_WT_BOSSSPAWN) || act->spr.pal != 22)) { act->clipdist = 20; act->spr.scale = DVector2(0.625, 0.625); } else { act->spr.scale = DVector2(1.25, 1.25); act->clipdist = 41; } } else { if (act->spr.picnum != DTILE_SHARK) { act->spr.scale = DVector2(0.625, 0.625); act->clipdist = 20; } else { act->spr.scale = DVector2(0.9375, 0.9375); act->clipdist = 10; } } 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 != DTILE_SHARK) ps[myconnectindex].max_actors_killed++; if (act->spr.picnum == DTILE_ORGANTIC) act->spr.cstat |= CSTAT_SPRITE_YCENTER; if (actj) { act->timetosleep = 0; check_fta_sounds_d(act); ChangeActorStat(act, STAT_ACTOR); } else ChangeActorStat(act, STAT_ZOMBIEACTOR); } if (act->spr.picnum == DTILE_ROTATEGUN) act->vel.Z = 0; break; case DTILE_FLAMETHROWERSPRITE: case DTILE_FLAMETHROWERAMMO: // Twentieth Anniversary World Tour if (!isWorldTour()) break; [[fallthrough]]; case DTILE_STEROIDS: case DTILE_HEATSENSOR: case DTILE_SHIELD: case DTILE_AIRTANK: case DTILE_TRIPBOMBSPRITE: case DTILE_JETPACK: case DTILE_HOLODUKE: case DTILE_FIRSTGUNSPRITE: case DTILE_CHAINGUNSPRITE: case DTILE_SHOTGUNSPRITE: case DTILE_RPGSPRITE: case DTILE_SHRINKERSPRITE: case DTILE_FREEZESPRITE: case DTILE_DEVISTATORSPRITE: case DTILE_SHOTGUNAMMO: case DTILE_FREEZEAMMO: case DTILE_HBOMBAMMO: case DTILE_CRYSTALAMMO: case DTILE_GROWAMMO: case DTILE_DEVISTATORAMMO: case DTILE_RPGAMMO: case DTILE_BOOTS: case DTILE_AMMO: case DTILE_AMMOLOTS: case DTILE_COLA: case DTILE_FIRSTAID: if (actj) { act->spr.lotag = 0; act->spr.pos.Z -= 32; act->vel.Z = -4; ssp(act, CLIPMASK0); if (krand() & 4) act->spr.cstat |= CSTAT_SPRITE_XFLIP; } 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 DTILE_ACCESSCARD: if (ud.multimode > 1 && ud.coop != 1 && act->spr.picnum == DTILE_ACCESSCARD) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); break; } else { if (act->spr.picnum == DTILE_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); } break; case DTILE_FLOORFLAME: act->spr.shade = -127; ChangeActorStat(act, STAT_STANDABLE); break; case DTILE_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 DTILE_CEILINGSTEAM: ChangeActorStat(act, STAT_STANDABLE); break; case DTILE_RUBBERCAN: act->spr.extra = 0; [[fallthrough]]; case DTILE_EXPLODINGBARREL: case DTILE_HORSEONSIDE: case DTILE_FIREBARREL: case DTILE_NUKEBARREL: case DTILE_FIREVASE: case DTILE_NUKEBARRELDENTED: case DTILE_NUKEBARRELLEAKED: case DTILE_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 DTILE_EGG: if (ud.monsters_off == 1 && act->spr.picnum == DTILE_EGG) { act->spr.scale = DVector2(0, 0); ChangeActorStat(act, STAT_MISC); } else { if (act->spr.picnum == DTILE_EGG) { act->clipdist = 6; ps[connecthead].max_actors_killed++; } act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL | randomXFlip(); ChangeActorStat(act, STAT_ZOMBIEACTOR); } break; } return act; } END_DUKE_NS