raze/source/games/duke/src/spawn_d.cpp

529 lines
12 KiB
C++
Raw Normal View History

2020-05-15 20:59:13 +00:00
//-------------------------------------------------------------------------
/*
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 <utility>
#include "ns.h"
#include "global.h"
2020-06-24 19:21:02 +00:00
#include "sounds.h"
#include "names_d.h"
2020-10-21 17:38:53 +00:00
#include "dukeactor.h"
2020-05-15 20:59:13 +00:00
BEGIN_DUKE_NS
DDukeActor* spawninit_d(DDukeActor* actj, DDukeActor* act, TArray<DDukeActor*>* actors)
2020-05-15 20:59:13 +00:00
{
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;
}
2022-01-16 23:51:40 +00:00
if (act->GetClass() != RUNTIME_CLASS(DDukeActor))
{
if (!badguy(act) || commonEnemySetup(act, actj))
CallInitialize(act);
2022-01-16 23:51:40 +00:00
return act;
}
auto sectp = act->sector();
2020-05-15 20:59:13 +00:00
if (isWorldTour())
{
2021-12-21 20:57:32 +00:00
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))
2021-12-21 20:57:32 +00:00
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;
2020-05-15 20:59:13 +00:00
}
}
else
{
act->spr.scale = DVector2(0.625, 0.625);
act->clipdist = 20;
2020-05-15 20:59:13 +00:00
}
2021-12-21 20:57:32 +00:00
if (actj)
act->spr.lotag = 0;
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:32 +00:00
if ((act->spr.lotag > ud.player_skill) || ud.monsters_off)
{
act->spr.scale = DVector2(0, 0);
ChangeActorStat(act, STAT_MISC);
2020-05-15 20:59:13 +00:00
break;
}
else
{
makeitfall(act);
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:32 +00:00
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
2020-05-15 20:59:13 +00:00
ps[connecthead].max_actors_killed++;
2021-12-21 20:57:32 +00:00
if (actj) {
2020-11-02 19:54:27 +00:00
act->timetosleep = 0;
check_fta_sounds_d(act);
ChangeActorStat(act, STAT_ACTOR);
}
else
ChangeActorStat(act, STAT_ZOMBIEACTOR);
2020-05-15 20:59:13 +00:00
}
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);
2021-12-21 20:57:32 +00:00
act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL;
act->spr.extra = 150;
return act;
2020-05-15 20:59:13 +00:00
}
}
2021-12-21 20:57:32 +00:00
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;
2021-12-21 20:57:32 +00:00
if (actj && actj->spr.pal == 6)
act->spr.pal = 6;
ChangeActorStat(act, STAT_MISC);
break;
case DTILE_FECES:
2021-12-21 20:57:32 +00:00
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:
2022-11-27 22:36:39 +00:00
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;
2021-12-21 20:57:32 +00:00
act->spr.shade = actj->spr.shade;
2022-09-01 14:42:23 +00:00
act->spr.pal = ps[actj->PlayerIndex()].palookup;
}
2021-12-21 20:57:32 +00:00
act->spr.cstat = 0;
act->spr.extra = 1;
2022-09-11 17:28:45 +00:00
act->vel.X = 292 / 16.;
act->vel.Z = 360 / 256.;
[[fallthrough]];
case DTILE_BLIMP:
2022-11-27 17:06:32 +00:00
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:
2021-12-21 20:57:32 +00:00
if (actj)
{
act->spr.Angles.Yaw = actj->spr.Angles.Yaw;
2021-12-21 20:57:32 +00:00
act->spr.shade = -64;
act->spr.cstat = CSTAT_SPRITE_YCENTER | randomXFlip();
}
act->spr.scale = DVector2(0.375, 0.375);
2021-12-21 20:57:32 +00:00
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);
2021-12-21 20:57:32 +00:00
act->spr.cstat |= CSTAT_SPRITE_YCENTER;
}
ChangeActorStat(act, STAT_MISC);
break;
case DTILE_PLAYERONWATER:
2021-12-21 20:57:32 +00:00
if (actj)
{
act->spr.scale = actj->spr.scale;
2022-09-03 08:04:16 +00:00
act->vel.Z = 0.5;
if (act->sector()->lotag != 2)
2021-12-21 20:57:32 +00:00
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;
2021-12-21 20:57:32 +00:00
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);
2022-10-05 22:01:01 +00:00
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));
2021-12-21 20:57:32 +00:00
act->spr.hitag = 0;
}
2021-12-21 20:57:32 +00:00
act->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
2022-09-11 21:16:06 +00:00
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:
2021-12-21 20:57:32 +00:00
if (act->spr.pal == 0)
{
2021-12-21 20:57:32 +00:00
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:
2021-12-21 20:57:32 +00:00
act->spr.pal = 22;
break;
}
}
2021-12-21 20:57:32 +00:00
if (bossguy(act))
{
if (actj && isrespawncontroller(actj))
2021-12-21 20:57:32 +00:00
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;
}
}
2021-12-21 20:57:32 +00:00
if (actj) act->spr.lotag = 0;
2021-12-21 20:57:32 +00:00
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);
2022-11-27 19:25:41 +00:00
act->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL;
if (act->spr.picnum != DTILE_SHARK)
2022-11-27 19:25:41 +00:00
ps[myconnectindex].max_actors_killed++;
if (act->spr.picnum == DTILE_ORGANTIC) act->spr.cstat |= CSTAT_SPRITE_YCENTER;
2021-12-21 20:57:32 +00:00
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)
2022-09-03 08:02:25 +00:00
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:
2021-12-21 20:57:32 +00:00
if (actj)
{
2021-12-21 20:57:32 +00:00
act->spr.lotag = 0;
act->spr.pos.Z -= 32;
2022-09-11 17:28:45 +00:00
act->vel.Z = -4;
ssp(act, CLIPMASK0);
2021-12-21 20:57:32 +00:00
if (krand() & 4) act->spr.cstat |= CSTAT_SPRITE_XFLIP;
}
else
{
act->SetOwner(act);
2021-12-21 20:57:32 +00:00
act->spr.cstat = 0;
}
2021-12-21 20:57:32 +00:00
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;
}
2021-12-21 20:57:32 +00:00
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);
}
2020-05-15 20:59:13 +00:00
2021-12-21 20:57:32 +00:00
act->spr.shade = -17;
2021-12-21 20:57:32 +00:00
if (actj) ChangeActorStat(act, STAT_ACTOR);
else
{
ChangeActorStat(act, STAT_ZOMBIEACTOR);
makeitfall(act);
}
break;
case DTILE_FLOORFLAME:
2021-12-21 20:57:32 +00:00
act->spr.shade = -127;
ChangeActorStat(act, STAT_STANDABLE);
break;
case DTILE_STEAM:
2021-12-21 20:57:32 +00:00
if (actj)
{
act->spr.Angles.Yaw = actj->spr.Angles.Yaw;
2021-12-21 20:57:32 +00:00
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:
2021-12-21 20:57:32 +00:00
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:
2021-12-21 20:57:32 +00:00
if (actj)
act->spr.scale = DVector2(0.5, 0.5);
act->clipdist = 18;
makeitfall(act);
2021-12-21 20:57:32 +00:00
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++;
}
2021-12-21 20:57:32 +00:00
act->spr.cstat = CSTAT_SPRITE_BLOCK_ALL | randomXFlip();
ChangeActorStat(act, STAT_ZOMBIEACTOR);
}
break;
}
return act;
2020-05-15 20:59:13 +00:00
}
END_DUKE_NS