2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#include "names2.h"
|
|
|
|
#include "panel.h"
|
2020-08-05 22:18:45 +00:00
|
|
|
#include "misc.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "tags.h"
|
|
|
|
#include "break.h"
|
2019-03-21 02:24:19 +00:00
|
|
|
#include "network.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "pal.h"
|
|
|
|
|
|
|
|
#include "ai.h"
|
|
|
|
#include "weapon.h"
|
|
|
|
|
|
|
|
#include "sprite.h"
|
|
|
|
#include "sector.h"
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
ANIMATOR DoSuicide;
|
2015-05-19 21:54:34 +00:00
|
|
|
ANIMATOR DoBloodSpray;
|
2021-10-31 08:04:24 +00:00
|
|
|
void SpawnFlashBombOnActor(DSWActor* actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
ANIMATOR DoPuff, BloodSprayFall;
|
|
|
|
extern STATE s_Puff[];
|
|
|
|
extern STATE s_FireballFlames[];
|
|
|
|
extern STATE s_GoreFloorSplash[];
|
|
|
|
extern STATE s_GoreSplash[];
|
2020-09-09 18:32:24 +00:00
|
|
|
extern bool GlobalSkipZrange;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
#define CHEMTICS SEC(40)
|
|
|
|
|
|
|
|
#define GOREDrip 1562 //2430
|
|
|
|
#define BLOODSPRAY_RATE 20
|
|
|
|
|
|
|
|
STATE s_BloodSpray[] =
|
|
|
|
{
|
|
|
|
{GOREDrip + 0, BLOODSPRAY_RATE, BloodSprayFall, &s_BloodSpray[1]},
|
|
|
|
{GOREDrip + 1, BLOODSPRAY_RATE, BloodSprayFall, &s_BloodSpray[2]},
|
|
|
|
{GOREDrip + 2, BLOODSPRAY_RATE, BloodSprayFall, &s_BloodSpray[3]},
|
|
|
|
{GOREDrip + 3, BLOODSPRAY_RATE, BloodSprayFall, &s_BloodSpray[4]},
|
|
|
|
{GOREDrip + 3, 100, DoSuicide, &s_BloodSpray[0]}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define EXP_RATE 2
|
|
|
|
STATE s_PhosphorExp[] =
|
|
|
|
{
|
|
|
|
{EXP + 0, EXP_RATE, NullAnimator, &s_PhosphorExp[1]},
|
|
|
|
{EXP + 1, EXP_RATE, NullAnimator, &s_PhosphorExp[2]},
|
|
|
|
{EXP + 2, EXP_RATE, NullAnimator, &s_PhosphorExp[3]},
|
|
|
|
{EXP + 3, EXP_RATE, NullAnimator, &s_PhosphorExp[4]},
|
|
|
|
{EXP + 4, EXP_RATE, NullAnimator, &s_PhosphorExp[5]},
|
|
|
|
{EXP + 5, EXP_RATE, NullAnimator, &s_PhosphorExp[6]},
|
|
|
|
{EXP + 6, EXP_RATE, NullAnimator, &s_PhosphorExp[7]},
|
|
|
|
{EXP + 7, EXP_RATE, NullAnimator, &s_PhosphorExp[8]},
|
|
|
|
{EXP + 8, EXP_RATE, NullAnimator, &s_PhosphorExp[9]},
|
|
|
|
{EXP + 9, EXP_RATE, NullAnimator, &s_PhosphorExp[10]},
|
|
|
|
{EXP + 10, EXP_RATE, NullAnimator, &s_PhosphorExp[11]},
|
|
|
|
{EXP + 11, EXP_RATE, NullAnimator, &s_PhosphorExp[12]},
|
|
|
|
{EXP + 12, EXP_RATE, NullAnimator, &s_PhosphorExp[13]},
|
|
|
|
{EXP + 13, EXP_RATE, NullAnimator, &s_PhosphorExp[14]},
|
|
|
|
{EXP + 14, EXP_RATE, NullAnimator, &s_PhosphorExp[15]},
|
|
|
|
{EXP + 15, EXP_RATE, NullAnimator, &s_PhosphorExp[16]},
|
|
|
|
{EXP + 16, EXP_RATE, NullAnimator, &s_PhosphorExp[17]},
|
|
|
|
{EXP + 17, EXP_RATE, NullAnimator, &s_PhosphorExp[18]},
|
|
|
|
{EXP + 18, EXP_RATE, NullAnimator, &s_PhosphorExp[19]},
|
|
|
|
{EXP + 19, EXP_RATE, NullAnimator, &s_PhosphorExp[20]},
|
|
|
|
{EXP + 20, 100, DoSuicide, &s_PhosphorExp[0]}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MUSHROOM_RATE 25
|
|
|
|
|
|
|
|
STATE s_NukeMushroom[] =
|
|
|
|
{
|
|
|
|
{MUSHROOM_CLOUD + 0, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[1]},
|
|
|
|
{MUSHROOM_CLOUD + 1, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[2]},
|
|
|
|
{MUSHROOM_CLOUD + 2, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[3]},
|
|
|
|
{MUSHROOM_CLOUD + 3, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[4]},
|
|
|
|
{MUSHROOM_CLOUD + 4, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[5]},
|
|
|
|
{MUSHROOM_CLOUD + 5, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[6]},
|
|
|
|
{MUSHROOM_CLOUD + 6, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[7]},
|
|
|
|
{MUSHROOM_CLOUD + 7, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[8]},
|
|
|
|
{MUSHROOM_CLOUD + 8, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[9]},
|
|
|
|
{MUSHROOM_CLOUD + 9, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[10]},
|
|
|
|
{MUSHROOM_CLOUD + 10, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[11]},
|
|
|
|
{MUSHROOM_CLOUD + 11, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[12]},
|
|
|
|
{MUSHROOM_CLOUD + 12, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[13]},
|
|
|
|
{MUSHROOM_CLOUD + 13, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[14]},
|
|
|
|
{MUSHROOM_CLOUD + 14, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[15]},
|
|
|
|
{MUSHROOM_CLOUD + 15, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[16]},
|
|
|
|
{MUSHROOM_CLOUD + 16, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[17]},
|
|
|
|
{MUSHROOM_CLOUD + 17, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[18]},
|
|
|
|
{MUSHROOM_CLOUD + 18, MUSHROOM_RATE, NullAnimator, &s_NukeMushroom[19]},
|
|
|
|
{MUSHROOM_CLOUD + 19, 100, DoSuicide, &s_NukeMushroom[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
ANIMATOR DoRadiationCloud;
|
|
|
|
|
|
|
|
#define RADIATION_RATE 16
|
|
|
|
|
|
|
|
STATE s_RadiationCloud[] =
|
|
|
|
{
|
|
|
|
{RADIATION_CLOUD + 0, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[1]},
|
|
|
|
{RADIATION_CLOUD + 1, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[2]},
|
|
|
|
{RADIATION_CLOUD + 2, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[3]},
|
|
|
|
{RADIATION_CLOUD + 3, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[4]},
|
|
|
|
{RADIATION_CLOUD + 4, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[5]},
|
|
|
|
{RADIATION_CLOUD + 5, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[6]},
|
|
|
|
{RADIATION_CLOUD + 6, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[7]},
|
|
|
|
{RADIATION_CLOUD + 7, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[8]},
|
|
|
|
{RADIATION_CLOUD + 8, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[9]},
|
|
|
|
{RADIATION_CLOUD + 9, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[10]},
|
|
|
|
{RADIATION_CLOUD + 10, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[11]},
|
|
|
|
{RADIATION_CLOUD + 11, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[12]},
|
|
|
|
{RADIATION_CLOUD + 12, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[13]},
|
|
|
|
{RADIATION_CLOUD + 13, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[14]},
|
|
|
|
{RADIATION_CLOUD + 14, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[15]},
|
|
|
|
{RADIATION_CLOUD + 15, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[16]},
|
|
|
|
{RADIATION_CLOUD + 16, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[17]},
|
|
|
|
{RADIATION_CLOUD + 17, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[18]},
|
|
|
|
{RADIATION_CLOUD + 18, RADIATION_RATE, DoRadiationCloud, &s_RadiationCloud[19]},
|
|
|
|
{RADIATION_CLOUD + 19, 100, DoSuicide, &s_RadiationCloud[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
#define CHEMBOMB_FRAMES 1
|
|
|
|
#define CHEMBOMB_R0 3038
|
|
|
|
#define CHEMBOMB_R1 CHEMBOMB_R0 + (CHEMBOMB_FRAMES * 1)
|
|
|
|
#define CHEMBOMB_R2 CHEMBOMB_R0 + (CHEMBOMB_FRAMES * 2)
|
|
|
|
#define CHEMBOMB_R3 CHEMBOMB_R0 + (CHEMBOMB_FRAMES * 3)
|
|
|
|
#define CHEMBOMB_R4 CHEMBOMB_R0 + (CHEMBOMB_FRAMES * 4)
|
|
|
|
|
|
|
|
#define CHEMBOMB CHEMBOMB_R0
|
|
|
|
#define CHEMBOMB_RATE 8
|
|
|
|
ANIMATOR DoChemBomb;
|
|
|
|
|
|
|
|
STATE s_ChemBomb[5] =
|
|
|
|
{
|
|
|
|
{CHEMBOMB_R0 + 0, CHEMBOMB_RATE, DoChemBomb, &s_ChemBomb[1]},
|
|
|
|
{CHEMBOMB_R1 + 0, CHEMBOMB_RATE, DoChemBomb, &s_ChemBomb[2]},
|
|
|
|
{CHEMBOMB_R2 + 0, CHEMBOMB_RATE, DoChemBomb, &s_ChemBomb[3]},
|
|
|
|
{CHEMBOMB_R3 + 0, CHEMBOMB_RATE, DoChemBomb, &s_ChemBomb[4]},
|
|
|
|
{CHEMBOMB_R4 + 0, CHEMBOMB_RATE, DoChemBomb, &s_ChemBomb[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define CALTROPS_FRAMES 1
|
|
|
|
#define CALTROPS_R0 CALTROPS-1
|
|
|
|
|
|
|
|
#define CALTROPS_RATE 8
|
|
|
|
|
|
|
|
ANIMATOR DoCaltrops, DoCaltropsStick;
|
|
|
|
|
|
|
|
STATE s_Caltrops[] =
|
|
|
|
{
|
|
|
|
{CALTROPS_R0 + 0, CALTROPS_RATE, DoCaltrops, &s_Caltrops[1]},
|
|
|
|
{CALTROPS_R0 + 1, CALTROPS_RATE, DoCaltrops, &s_Caltrops[2]},
|
|
|
|
{CALTROPS_R0 + 2, CALTROPS_RATE, DoCaltrops, &s_Caltrops[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
STATE s_CaltropsStick[] =
|
|
|
|
{
|
|
|
|
{CALTROPS_R0 + 2, CALTROPS_RATE, DoCaltropsStick, &s_CaltropsStick[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////
|
|
|
|
//
|
|
|
|
// CAPTURE FLAG
|
|
|
|
//
|
|
|
|
//////////////////////
|
|
|
|
|
|
|
|
ANIMATOR DoFlag, DoCarryFlag, DoCarryFlagNoDet;
|
|
|
|
|
|
|
|
#undef FLAG
|
|
|
|
#define FLAG 2520
|
|
|
|
#define FLAG_RATE 16
|
|
|
|
|
|
|
|
STATE s_CarryFlag[] =
|
|
|
|
{
|
|
|
|
{FLAG + 0, FLAG_RATE, DoCarryFlag, &s_CarryFlag[1]},
|
|
|
|
{FLAG + 1, FLAG_RATE, DoCarryFlag, &s_CarryFlag[2]},
|
|
|
|
{FLAG + 2, FLAG_RATE, DoCarryFlag, &s_CarryFlag[0]}
|
|
|
|
};
|
|
|
|
|
|
|
|
STATE s_CarryFlagNoDet[] =
|
|
|
|
{
|
|
|
|
{FLAG + 0, FLAG_RATE, DoCarryFlagNoDet, &s_CarryFlagNoDet[1]},
|
|
|
|
{FLAG + 1, FLAG_RATE, DoCarryFlagNoDet, &s_CarryFlagNoDet[2]},
|
|
|
|
{FLAG + 2, FLAG_RATE, DoCarryFlagNoDet, &s_CarryFlagNoDet[0]}
|
|
|
|
};
|
|
|
|
|
|
|
|
STATE s_Flag[] =
|
|
|
|
{
|
|
|
|
{FLAG + 0, FLAG_RATE, DoFlag, &s_Flag[1]},
|
|
|
|
{FLAG + 1, FLAG_RATE, DoFlag, &s_Flag[2]},
|
|
|
|
{FLAG + 2, FLAG_RATE, DoFlag, &s_Flag[0]}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define PHOSPHORUS_RATE 8
|
|
|
|
ANIMATOR DoPhosphorus;
|
|
|
|
|
|
|
|
STATE s_Phosphorus[] =
|
|
|
|
{
|
|
|
|
{PHOSPHORUS + 0, PHOSPHORUS_RATE, DoPhosphorus, &s_Phosphorus[1]},
|
|
|
|
{PHOSPHORUS + 1, PHOSPHORUS_RATE, DoPhosphorus, &s_Phosphorus[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
ANIMATOR DoBloodSpray;
|
|
|
|
|
|
|
|
#define CHUNK1 1685
|
|
|
|
STATE s_BloodSprayChunk[] =
|
|
|
|
{
|
|
|
|
{CHUNK1 + 0, 8, DoBloodSpray, &s_BloodSprayChunk[1]},
|
|
|
|
{CHUNK1 + 1, 8, DoBloodSpray, &s_BloodSprayChunk[2]},
|
|
|
|
{CHUNK1 + 2, 8, DoBloodSpray, &s_BloodSprayChunk[3]},
|
|
|
|
{CHUNK1 + 3, 8, DoBloodSpray, &s_BloodSprayChunk[4]},
|
|
|
|
{CHUNK1 + 4, 8, DoBloodSpray, &s_BloodSprayChunk[5]},
|
|
|
|
{CHUNK1 + 5, 8, DoBloodSpray, &s_BloodSprayChunk[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
ANIMATOR DoWallBloodDrip;
|
|
|
|
|
|
|
|
#define DRIP 1566
|
|
|
|
STATE s_BloodSprayDrip[] =
|
|
|
|
{
|
|
|
|
{DRIP + 0, PHOSPHORUS_RATE, DoWallBloodDrip, &s_BloodSprayDrip[1]},
|
|
|
|
{DRIP + 1, PHOSPHORUS_RATE, DoWallBloodDrip, &s_BloodSprayDrip[2]},
|
|
|
|
{DRIP + 2, PHOSPHORUS_RATE, DoWallBloodDrip, &s_BloodSprayDrip[0]},
|
|
|
|
};
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2021-11-01 08:23:52 +00:00
|
|
|
int DoWallBloodDrip(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 08:23:52 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
//sp->z += (300+RandomRange(2300)) >> 1;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// sy & sz are the ceiling and floor of the sector you are sliding down
|
|
|
|
if (u->sz != u->sy)
|
|
|
|
{
|
|
|
|
// if you are between the ceiling and floor fall fast
|
|
|
|
if (sp->z > u->sy && sp->z < u->sz)
|
|
|
|
{
|
|
|
|
sp->zvel += 300;
|
|
|
|
sp->z += sp->zvel;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-20 06:59:54 +00:00
|
|
|
sp->zvel = (300+RandomRange(2300)) >> 1;
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->z += sp->zvel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-20 06:59:54 +00:00
|
|
|
sp->zvel = (300+RandomRange(2300)) >> 1;
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->z += sp->zvel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp->z >= u->loz)
|
|
|
|
{
|
|
|
|
sp->z = u->loz;
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnFloorSplash(actor);
|
2021-10-30 20:53:24 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 08:31:36 +00:00
|
|
|
void SpawnMidSplash(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 08:23:52 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp np;
|
|
|
|
USERp nu;
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, GOREDrip, s_GoreSplash, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, SPRITEp_MID(sp), sp->ang, 0);
|
|
|
|
|
2021-11-01 08:23:52 +00:00
|
|
|
np = &actorNew->s();
|
|
|
|
nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
np->shade = -12;
|
2021-09-20 06:59:54 +00:00
|
|
|
np->xrepeat = 70-RandomRange(20);
|
|
|
|
np->yrepeat = 70-RandomRange(20);
|
2021-01-05 12:43:49 +00:00
|
|
|
np->opos = sp->opos;
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_XFLIP);
|
|
|
|
|
|
|
|
nu->xchange = 0;
|
|
|
|
nu->ychange = 0;
|
|
|
|
nu->zchange = 0;
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(nu->Flags, SPR_UNDERWATER);
|
|
|
|
}
|
|
|
|
|
2021-11-01 08:23:52 +00:00
|
|
|
void SpawnFloorSplash(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 08:23:52 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp np;
|
|
|
|
USERp nu;
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, GOREDrip, s_GoreFloorSplash, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, sp->z, sp->ang, 0);
|
|
|
|
|
2021-11-01 08:23:52 +00:00
|
|
|
np = &actorNew->s();
|
|
|
|
nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
np->shade = -12;
|
2021-09-20 06:59:54 +00:00
|
|
|
np->xrepeat = 70-RandomRange(20);
|
|
|
|
np->yrepeat = 70-RandomRange(20);
|
2021-01-05 12:43:49 +00:00
|
|
|
np->opos = sp->opos;
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_XFLIP);
|
|
|
|
|
|
|
|
nu->xchange = 0;
|
|
|
|
nu->ychange = 0;
|
|
|
|
nu->zchange = 0;
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(nu->Flags, SPR_UNDERWATER);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-01 08:31:36 +00:00
|
|
|
int DoBloodSpray(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 08:31:36 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
int cz,fz;
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
{
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 50000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->Counter += 20; // These are STAT_SKIIP4 now, so * 2
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->Counter += 20;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp->xvel <= 2)
|
|
|
|
{
|
|
|
|
// special stuff for blood worm
|
|
|
|
sp->z += (u->zchange >> 1);
|
|
|
|
|
2021-11-24 18:25:13 +00:00
|
|
|
getzsofslopeptr(sp->sector(), sp->x, sp->y, &cz, &fz);
|
2015-05-19 21:54:34 +00:00
|
|
|
// pretend like we hit a sector
|
|
|
|
if (sp->z >= fz)
|
|
|
|
{
|
|
|
|
sp->z = fz;
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnFloorSplash(actor);
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-05 20:37:49 +00:00
|
|
|
u->coll = move_missile(actor, u->xchange, u->ychange, u->zchange,
|
|
|
|
u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-03 16:52:16 +00:00
|
|
|
MissileHitDiveArea(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
switch (u->coll.type)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSky:
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSprite:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short wall_ang;
|
2021-11-01 09:48:45 +00:00
|
|
|
auto hitActor = u->coll.actor;
|
|
|
|
SPRITEp hsp = &hitActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2018-02-16 06:38:31 +00:00
|
|
|
if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
wall_ang = NORM_ANGLE(hsp->ang);
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnMidSplash(actor);
|
2021-11-02 17:51:14 +00:00
|
|
|
QueueWallBlood(actor, hsp->ang);
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnMidSplash(actor);
|
2021-11-02 17:51:14 +00:00
|
|
|
QueueWallBlood(actor, hsp->ang);
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitWall:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short hit_wall, nw, wall_ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
WALLp wph;
|
|
|
|
short wb;
|
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
wph = u->coll.wall();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (wph->lotag == TAG_WALL_BREAK)
|
|
|
|
{
|
|
|
|
HitBreakWall(wph, sp->x, sp->y, sp->z, sp->ang, u->ID);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
wall_ang = NORM_ANGLE(getangle(wph->delta()) + 512);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnMidSplash(actor);
|
2021-11-02 17:51:14 +00:00
|
|
|
auto bldActor = QueueWallBlood(actor, NORM_ANGLE(wall_ang+1024));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 17:51:14 +00:00
|
|
|
if (bldActor== nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-02 17:51:14 +00:00
|
|
|
auto bsp = &bldActor->s();
|
2021-11-25 17:53:40 +00:00
|
|
|
if (FAF_Sector(bsp->sector()) || FAF_ConnectArea(bsp->sector()))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sp->xvel = sp->yvel = u->xchange = u->ychange = 0;
|
2021-09-20 06:59:54 +00:00
|
|
|
sp->xrepeat = sp->yrepeat = 70 - RandomRange(25);
|
2021-11-02 17:51:14 +00:00
|
|
|
sp->x = bsp->x;
|
|
|
|
sp->y = bsp->y;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// !FRANK! bit of a hack
|
2015-05-19 22:01:22 +00:00
|
|
|
// yvel is the hit_wall
|
2021-11-24 19:11:50 +00:00
|
|
|
if (bldActor->tempwall)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// sy & sz are the ceiling and floor of the sector you are sliding down
|
2021-11-24 19:11:50 +00:00
|
|
|
if (bldActor->tempwall->twoSided())
|
|
|
|
getzsofslopeptr(bldActor->tempwall->nextSector(), sp->x, sp->y, &u->sy, &u->sz);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
u->sy = u->sz; // ceiling and floor are equal - white wall
|
|
|
|
}
|
|
|
|
|
|
|
|
RESET(sp->cstat,CSTAT_SPRITE_INVISIBLE);
|
2021-11-01 08:31:36 +00:00
|
|
|
ChangeState(actor, s_BloodSprayDrip);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSector:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit floor
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing
|
|
|
|
// underwater
|
|
|
|
|
2021-11-20 22:20:43 +00:00
|
|
|
if (u->lo_sectp && sp->sector()->hasU() && FixedToInt(sp->sector()->depth_fixed))
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing on
|
|
|
|
// shallow water
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnFloorSplash(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // Was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
u->zchange /= 6;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
2021-11-01 08:23:52 +00:00
|
|
|
SpawnFloorSplash(actor);
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// hit something above
|
|
|
|
{
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if you haven't bounced or your going slow do some puffs
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE | SPR_UNDERWATER))
|
|
|
|
{
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, GOREDrip, s_BloodSpray, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, sp->z, sp->ang, 100);
|
|
|
|
|
2021-11-01 08:31:36 +00:00
|
|
|
auto np = &actorNew->s();
|
|
|
|
auto nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 08:31:36 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
np->shade = -12;
|
2021-09-20 06:59:54 +00:00
|
|
|
np->xrepeat = 40-RandomRange(30);
|
|
|
|
np->yrepeat = 40-RandomRange(30);
|
2021-01-05 12:43:49 +00:00
|
|
|
np->opos = sp->opos;
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_XFLIP);
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_YFLIP);
|
|
|
|
|
|
|
|
nu->xchange = u->xchange;
|
|
|
|
nu->ychange = u->ychange;
|
|
|
|
nu->zchange = u->zchange;
|
|
|
|
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actorNew, 20000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(nu->Flags, SPR_UNDERWATER);
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-01 08:39:44 +00:00
|
|
|
int DoPhosphorus(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 08:39:44 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
{
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 50000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->Counter += 20*2;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->Counter += 20*2;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
|
2021-11-05 20:37:49 +00:00
|
|
|
u->coll = move_missile(actor, u->xchange, u->ychange, u->zchange,
|
|
|
|
u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS*2);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:52:16 +00:00
|
|
|
MissileHitDiveArea(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER) && (RANDOM_P2(1024 << 4) >> 4) < 256)
|
2021-11-01 20:58:16 +00:00
|
|
|
SpawnBubble(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
switch (u->coll.type)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSky:
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSprite:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short wall_ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp hsp;
|
|
|
|
USERp hu;
|
|
|
|
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
auto hitActor = u->coll.actor;
|
|
|
|
hsp = &hitActor->s();
|
|
|
|
hu = hitActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2018-02-16 06:38:31 +00:00
|
|
|
if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
wall_ang = NORM_ANGLE(hsp->ang);
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (TEST(hsp->extra, SPRX_BURNABLE))
|
|
|
|
{
|
|
|
|
if (!hu)
|
2021-11-01 09:48:45 +00:00
|
|
|
hu = SpawnUser(hitActor, hsp->picnum, nullptr);
|
2021-11-03 17:29:28 +00:00
|
|
|
SpawnFireballExp(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
if (hu)
|
2021-11-05 15:54:28 +00:00
|
|
|
SpawnFireballFlames(actor, hitActor);
|
2021-11-05 21:22:28 +00:00
|
|
|
DoFlamesDamageTest(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
u->xchange = u->ychange = 0;
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitWall:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short hit_wall, nw, wall_ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
WALLp wph;
|
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
wph = u->coll.wall();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (wph->lotag == TAG_WALL_BREAK)
|
|
|
|
{
|
|
|
|
HitBreakWall(wph, sp->x, sp->y, sp->z, sp->ang, u->ID);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
wall_ang = NORM_ANGLE(getangle(wph->delta()) + 512);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSector:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-09 18:32:24 +00:00
|
|
|
bool did_hit_wall;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 21:02:01 +00:00
|
|
|
if (SlopeBounce(actor, &did_hit_wall))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:01:22 +00:00
|
|
|
if (did_hit_wall)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a wall
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 28000);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a sector
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a floor
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
u->zchange /= 6;
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
2021-11-03 17:29:28 +00:00
|
|
|
SpawnFireballExp(actor);
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a ceiling
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit floor
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing
|
|
|
|
// underwater
|
|
|
|
|
2021-11-20 22:20:43 +00:00
|
|
|
if (u->lo_sectp && sp->sector()->hasU() && FixedToInt(sp->sector()->depth_fixed))
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing on
|
|
|
|
// shallow water
|
|
|
|
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // Was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
u->zchange /= 6;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
2021-11-03 17:29:28 +00:00
|
|
|
SpawnFireballExp(actor);
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// hit something above
|
|
|
|
{
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if you haven't bounced or your going slow do some puffs
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE | SPR_UNDERWATER) && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
|
|
{
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_SKIP4, PUFF, s_PhosphorExp, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, sp->z, sp->ang, 100);
|
|
|
|
|
2021-11-01 08:39:44 +00:00
|
|
|
auto np = &actorNew->s();
|
|
|
|
auto nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
np->hitag = LUMINOUS; // Always full brightness
|
2021-11-01 08:39:44 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
np->shade = -40;
|
2021-09-20 06:59:54 +00:00
|
|
|
np->xrepeat = 12 + RandomRange(10);
|
|
|
|
np->yrepeat = 12 + RandomRange(10);
|
2021-01-05 12:43:49 +00:00
|
|
|
np->opos = sp->opos;
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_XFLIP);
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_YFLIP);
|
|
|
|
|
|
|
|
nu->xchange = u->xchange;
|
|
|
|
nu->ychange = u->ychange;
|
|
|
|
nu->zchange = u->zchange;
|
|
|
|
|
|
|
|
nu->spal = np->pal = PALETTE_PLAYER3; // RED
|
|
|
|
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actorNew, 20000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(nu->Flags, SPR_UNDERWATER);
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 08:49:37 +00:00
|
|
|
int DoChemBomb(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 08:49:37 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
{
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 50000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->Counter += 20;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->Counter += 20;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
|
2021-11-05 20:37:49 +00:00
|
|
|
u->coll = move_missile(actor, u->xchange, u->ychange, u->zchange,
|
|
|
|
u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:52:16 +00:00
|
|
|
MissileHitDiveArea(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER) && (RANDOM_P2(1024 << 4) >> 4) < 256)
|
2021-11-01 20:58:16 +00:00
|
|
|
SpawnBubble(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
switch (u->coll.type)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSky:
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSprite:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short wall_ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp hsp;
|
|
|
|
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CHEMBOUNCE, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
hsp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2018-02-16 06:38:31 +00:00
|
|
|
if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
wall_ang = NORM_ANGLE(hsp->ang);
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Canister pops when first smoke starts out
|
|
|
|
if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GASPOP, actor, v3df_dontpan | v3df_doppler);
|
|
|
|
PlaySound(DIGI_CHEMGAS, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
u->WaitTics -= (MISSILEMOVETICS * 2);
|
|
|
|
if (u->WaitTics <= 0)
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitWall:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 15:55:24 +00:00
|
|
|
auto wph = u->coll.wall();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (wph->lotag == TAG_WALL_BREAK)
|
|
|
|
{
|
|
|
|
HitBreakWall(wph, sp->x, sp->y, sp->z, sp->ang, u->ID);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CHEMBOUNCE, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
int wall_ang = NORM_ANGLE(getangle(wph->delta()) + 512);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSector:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-09 18:32:24 +00:00
|
|
|
bool did_hit_wall;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 21:02:01 +00:00
|
|
|
if (SlopeBounce(actor, &did_hit_wall))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:01:22 +00:00
|
|
|
if (did_hit_wall)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a wall
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 28000);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a sector
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a floor
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CHEMBOUNCE, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
u->zchange /= 6;
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Canister pops when first smoke starts out
|
|
|
|
if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GASPOP, actor, v3df_dontpan | v3df_doppler);
|
|
|
|
PlaySound(DIGI_CHEMGAS, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-11-01 09:51:25 +00:00
|
|
|
SpawnRadiationCloud(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
u->WaitTics -= (MISSILEMOVETICS * 2);
|
|
|
|
if (u->WaitTics <= 0)
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a ceiling
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit floor
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing
|
|
|
|
// underwater
|
|
|
|
|
2021-11-20 22:20:43 +00:00
|
|
|
if (u->lo_sectp && sp->sector()->hasU() && FixedToInt(sp->sector()->depth_fixed))
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing on
|
|
|
|
// shallow water
|
|
|
|
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CHEMBOUNCE, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // Was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
u->zchange /= 6;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Canister pops when first smoke starts out
|
|
|
|
if (u->WaitTics == CHEMTICS && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GASPOP, actor, v3df_dontpan | v3df_doppler);
|
|
|
|
PlaySound(DIGI_CHEMGAS, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
2021-11-01 09:51:25 +00:00
|
|
|
SpawnRadiationCloud(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
u->WaitTics -= (MISSILEMOVETICS * 2);
|
|
|
|
if (u->WaitTics <= 0)
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// hit something above
|
|
|
|
{
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 32000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if you haven't bounced or your going slow do some puffs
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE | SPR_UNDERWATER) && !TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
|
|
|
|
{
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, PUFF, s_Puff, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, sp->z, sp->ang, 100);
|
|
|
|
|
2021-11-01 08:49:37 +00:00
|
|
|
auto np = &actorNew->s();
|
|
|
|
auto nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 08:49:37 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
np->shade = -40;
|
|
|
|
np->xrepeat = 40;
|
|
|
|
np->yrepeat = 40;
|
2021-01-05 12:43:49 +00:00
|
|
|
np->opos = sp->opos;
|
2015-05-19 21:54:34 +00:00
|
|
|
// !Frank - dont do translucent
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
// SET(np->cstat, CSTAT_SPRITE_YCENTER|CSTAT_SPRITE_TRANSLUCENT);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
nu->xchange = u->xchange;
|
|
|
|
nu->ychange = u->ychange;
|
|
|
|
nu->zchange = u->zchange;
|
|
|
|
|
|
|
|
nu->spal = np->pal = PALETTE_PLAYER6;
|
|
|
|
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actorNew, 20000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(nu->Flags, SPR_UNDERWATER);
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 08:49:37 +00:00
|
|
|
int DoCaltropsStick(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->Counter = !u->Counter;
|
|
|
|
|
|
|
|
if (u->Counter)
|
2021-11-05 21:22:28 +00:00
|
|
|
DoFlamesDamageTest(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:36:41 +00:00
|
|
|
int DoCaltrops(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 09:36:41 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
{
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 50000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
u->Counter += 20;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->Counter += 70;
|
|
|
|
u->zchange += u->Counter;
|
|
|
|
}
|
|
|
|
|
2021-11-05 20:37:49 +00:00
|
|
|
u->coll = move_missile(actor, u->xchange, u->ychange, u->zchange,
|
|
|
|
u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:52:16 +00:00
|
|
|
MissileHitDiveArea(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
switch (u->coll.type)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSky:
|
2021-10-30 21:00:37 +00:00
|
|
|
KillActor(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSprite:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-03-06 15:49:49 +00:00
|
|
|
short wall_ang;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CALTROPS, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
auto hitActor = u->coll.actor;
|
|
|
|
auto hsp = &hitActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2018-02-16 06:38:31 +00:00
|
|
|
if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
wall_ang = NORM_ANGLE(hsp->ang);
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 10000);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// fall to the ground
|
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitWall:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-24 15:55:24 +00:00
|
|
|
auto wph = u->coll.wall();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (wph->lotag == TAG_WALL_BREAK)
|
|
|
|
{
|
|
|
|
HitBreakWall(wph, sp->x, sp->y, sp->z, sp->ang, u->ID);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CALTROPS, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
int wall_ang = NORM_ANGLE(getangle(wph->delta()) + 512);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 16:55:17 +00:00
|
|
|
WallBounce(actor, wall_ang);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
case kHitSector:
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2020-09-09 18:32:24 +00:00
|
|
|
bool did_hit_wall;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-03 21:02:01 +00:00
|
|
|
if (SlopeBounce(actor, &did_hit_wall))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:01:22 +00:00
|
|
|
if (did_hit_wall)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a wall
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a sector
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// hit a floor
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CALTROPS, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000); // was 18000
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
SET(sp->extra, SPRX_BREAKABLE);
|
|
|
|
SET(sp->cstat,CSTAT_SPRITE_BREAKABLE);
|
2021-11-01 09:36:41 +00:00
|
|
|
ChangeState(actor, s_CaltropsStick);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit a ceiling
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// hit floor
|
2021-11-19 20:47:04 +00:00
|
|
|
if (sp->z > ((u->hiz + u->loz) >> 1))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing
|
|
|
|
// underwater
|
|
|
|
|
2021-11-20 22:20:43 +00:00
|
|
|
if (u->lo_sectp && sp->sector()->hasU() && FixedToInt(sp->sector()->depth_fixed))
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE); // no bouncing on
|
|
|
|
// shallow water
|
|
|
|
|
|
|
|
if (!TEST(u->Flags, SPR_BOUNCE))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_CALTROPS, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
2021-11-05 20:12:01 +00:00
|
|
|
u->coll.setNone();
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter = 0;
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000); // Was 18000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u->xchange = u->ychange = 0;
|
|
|
|
SET(sp->extra, SPRX_BREAKABLE);
|
|
|
|
SET(sp->cstat,CSTAT_SPRITE_BREAKABLE);
|
2021-11-01 09:36:41 +00:00
|
|
|
ChangeState(actor, s_CaltropsStick);
|
2020-09-09 17:52:52 +00:00
|
|
|
return true;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// hit something above
|
|
|
|
{
|
|
|
|
u->zchange = -u->zchange;
|
2021-11-01 12:08:41 +00:00
|
|
|
ScaleSpriteVector(actor, 1000); // was 22000
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
//
|
|
|
|
// Deadly green gas clouds
|
|
|
|
//
|
|
|
|
/////////////////////////////
|
|
|
|
|
2021-11-01 09:51:25 +00:00
|
|
|
int SpawnRadiationCloud(DSWActor* actor)
|
|
|
|
{
|
|
|
|
SPRITEp sp = &actor->s(), np;
|
|
|
|
USERp u = actor->u(), nu;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (!MoveSkip4)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// This basically works like a MoveSkip8, if one existed
|
|
|
|
// u->Counter2 = !u->Counter2;
|
|
|
|
if (u->ID == MUSHROOM_CLOUD || u->ID == 3121)
|
|
|
|
{
|
|
|
|
if ((u->Counter2++) > 16)
|
|
|
|
u->Counter2 = 0;
|
|
|
|
if (u->Counter2)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((u->Counter2++) > 2)
|
|
|
|
u->Counter2 = 0;
|
|
|
|
if (u->Counter2)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (TEST(u->Flags, SPR_UNDERWATER))
|
|
|
|
return -1;
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, RADIATION_CLOUD, s_RadiationCloud, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->x, sp->y, sp->z - RANDOM_P2(Z(8)), sp->ang, 0);
|
|
|
|
|
2021-11-01 09:51:25 +00:00
|
|
|
np = &actorNew->s();
|
|
|
|
nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:51:25 +00:00
|
|
|
SetOwner(GetOwner(actor), actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
nu->WaitTics = 1 * 120;
|
|
|
|
np->shade = -40;
|
|
|
|
np->xrepeat = 32;
|
|
|
|
np->yrepeat = 32;
|
|
|
|
np->clipdist = sp->clipdist;
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
nu->spal = np->pal = PALETTE_PLAYER6;
|
|
|
|
// Won't take floor palettes
|
|
|
|
np->hitag = SECTFU_DONT_COPY_PALETTE;
|
|
|
|
|
|
|
|
if (RANDOM_P2(1024) < 512)
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_XFLIP);
|
|
|
|
//if (RANDOM_P2(1024) < 512)
|
|
|
|
//SET(np->cstat, CSTAT_SPRITE_YFLIP);
|
|
|
|
|
|
|
|
np->ang = RANDOM_P2(2048);
|
|
|
|
np->xvel = RANDOM_P2(32);
|
|
|
|
|
|
|
|
nu->Counter = 0;
|
|
|
|
nu->Counter2 = 0;
|
|
|
|
|
|
|
|
if (u->ID == MUSHROOM_CLOUD || u->ID == 3121)
|
|
|
|
{
|
|
|
|
nu->Radius = 2000;
|
|
|
|
nu->xchange = (MOVEx(np->xvel>>2, np->ang));
|
|
|
|
nu->ychange = (MOVEy(np->xvel>>2, np->ang));
|
|
|
|
np->zvel = Z(1) + RANDOM_P2(Z(2));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nu->xchange = MOVEx(np->xvel, np->ang);
|
|
|
|
nu->ychange = MOVEy(np->xvel, np->ang);
|
|
|
|
np->zvel = Z(4) + RANDOM_P2(Z(4));
|
|
|
|
nu->Radius = 4000;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 09:51:25 +00:00
|
|
|
int DoRadiationCloud(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 09:51:25 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sp->z -= sp->zvel;
|
|
|
|
|
|
|
|
sp->x += u->xchange;
|
|
|
|
sp->y += u->ychange;
|
|
|
|
|
|
|
|
if (u->ID)
|
|
|
|
{
|
2021-11-05 21:22:28 +00:00
|
|
|
DoFlamesDamageTest(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Inventory Chemical Bombs
|
|
|
|
//
|
|
|
|
//////////////////////////////////////////////
|
2021-11-01 09:59:10 +00:00
|
|
|
int PlayerInitChemBomb(PLAYERp pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:59:10 +00:00
|
|
|
USERp u = pp->Actor()->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
|
|
|
short oclipdist;
|
|
|
|
|
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlaySound(DIGI_THROW, pp, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 20:45:03 +00:00
|
|
|
if (!pp->insector())
|
2019-12-03 09:44:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
nx = pp->posx;
|
|
|
|
ny = pp->posy;
|
|
|
|
nz = pp->posz + pp->bob_z + Z(8);
|
|
|
|
|
|
|
|
// Spawn a shot
|
|
|
|
// Inserting and setting up variables
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, CHEMBOMB, s_ChemBomb, pp->cursector(),
|
2020-10-08 03:23:29 +00:00
|
|
|
nx, ny, nz, pp->angle.ang.asbuild(), CHEMBOMB_VELOCITY);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:59:10 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// don't throw it as far if crawling
|
|
|
|
if (TEST(pp->Flags, PF_CRAWLING))
|
|
|
|
{
|
2021-11-19 20:47:04 +00:00
|
|
|
wp->xvel -= (wp->xvel >> 2);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// wu->RotNum = 5;
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
|
2021-11-01 09:59:10 +00:00
|
|
|
SetOwner(pp->Actor(), actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->yrepeat = 32;
|
|
|
|
wp->xrepeat = 32;
|
|
|
|
wp->shade = -15;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 200;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
|
|
|
if (TEST(pp->Flags, PF_DIVING) || SpriteInUnderwaterArea(wp))
|
|
|
|
SET(wu->Flags, SPR_UNDERWATER);
|
|
|
|
|
2020-10-07 07:08:57 +00:00
|
|
|
wp->zvel = -pp->horizon.horiz.asq16() >> 9;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-07 07:08:57 +00:00
|
|
|
// //DSPRINTF(ds,"horiz %d, ho %d, ho+ho %d", pp->horizon.horiz.asbuild(), pp->horizon.horizoff.asbuild(),
|
|
|
|
// pp->horizon.horizoff.asbuild() + pp->horizon.horiz.asbuild());
|
2015-05-19 21:54:34 +00:00
|
|
|
// MONO_PRINT(ds);
|
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
auto psp = &pp->Actor()->s();
|
|
|
|
oclipdist = psp->clipdist;
|
|
|
|
psp->clipdist = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->clipdist = 0;
|
|
|
|
|
|
|
|
// wp->ang = NORM_ANGLE(wp->ang - 512);
|
2021-11-04 22:27:04 +00:00
|
|
|
// HelpMissileLateral(actorNew, 800);
|
2015-05-19 21:54:34 +00:00
|
|
|
// wp->ang = NORM_ANGLE(wp->ang + 512);
|
|
|
|
|
2021-11-04 23:02:40 +00:00
|
|
|
MissileSetPos(actorNew, DoChemBomb, 1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
psp->clipdist = uint8_t(oclipdist);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->clipdist = 80L >> 2;
|
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
|
|
|
|
// adjust xvel according to player velocity
|
|
|
|
wu->xchange += pp->xvect >> 14;
|
|
|
|
wu->ychange += pp->yvect >> 14;
|
|
|
|
|
|
|
|
// Smoke will come out for this many seconds
|
|
|
|
wu->WaitTics = CHEMTICS;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 09:59:10 +00:00
|
|
|
int InitSpriteChemBomb(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 09:59:10 +00:00
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
2021-11-01 09:59:10 +00:00
|
|
|
SPRITEp sp = &actor->s(), wp;
|
2015-05-19 21:54:34 +00:00
|
|
|
int nx, ny, nz;
|
|
|
|
|
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_THROW, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = sp->z;
|
|
|
|
|
|
|
|
// Spawn a shot
|
|
|
|
// Inserting and setting up variables
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, CHEMBOMB, s_ChemBomb, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
nx, ny, nz, sp->ang, CHEMBOMB_VELOCITY);
|
|
|
|
|
2021-11-01 09:59:10 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
|
2021-11-01 09:59:10 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->yrepeat = 32;
|
|
|
|
wp->xrepeat = 32;
|
|
|
|
wp->shade = -15;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 200;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->zvel = short(-RandomRange(100) * HORIZ_MULT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
wp->clipdist = 80L >> 2;
|
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
|
|
|
|
// Smoke will come out for this many seconds
|
|
|
|
wu->WaitTics = CHEMTICS;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-01 10:30:28 +00:00
|
|
|
int InitChemBomb(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:30:28 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
|
|
|
|
|
|
|
|
|
|
|
// Need to make it take away from inventory weapon list
|
|
|
|
// PlayerUpdateAmmo(pp, u->WeaponNum, -1);
|
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = sp->z;
|
|
|
|
|
|
|
|
// Spawn a shot
|
|
|
|
// Inserting and setting up variables
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, MUSHROOM_CLOUD, s_ChemBomb, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
nx, ny, nz, sp->ang, CHEMBOMB_VELOCITY);
|
|
|
|
|
2021-11-01 10:30:28 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
|
2021-11-01 10:30:28 +00:00
|
|
|
SetOwner(GetOwner(actor), actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->yrepeat = 32;
|
|
|
|
wp->xrepeat = 32;
|
|
|
|
wp->shade = -15;
|
|
|
|
wu->Radius = 200;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_INVISIBLE); // Make nuke radiation
|
|
|
|
// invis.
|
|
|
|
RESET(wp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
|
|
|
if (SpriteInUnderwaterArea(wp))
|
|
|
|
SET(wu->Flags, SPR_UNDERWATER);
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->zvel = short(-RandomRange(100) * HORIZ_MULT);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->clipdist = 0;
|
|
|
|
|
|
|
|
if (u->ID == MUSHROOM_CLOUD || u->ID == 3121 || u->ID == SUMO_RUN_R0) // 3121 == GRENADE_EXP
|
|
|
|
{
|
|
|
|
wu->xchange = 0;
|
|
|
|
wu->ychange = 0;
|
|
|
|
wu->zchange = 0;
|
|
|
|
wp->xvel = wp->yvel = wp->zvel = 0;
|
|
|
|
// Smoke will come out for this many seconds
|
|
|
|
wu->WaitTics = 40*120;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
// Smoke will come out for this many seconds
|
|
|
|
wu->WaitTics = 3*120;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Inventory Flash Bombs
|
|
|
|
//
|
|
|
|
//////////////////////////////////////////////
|
2021-11-01 10:30:28 +00:00
|
|
|
|
|
|
|
int PlayerInitFlashBomb(PLAYERp pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
unsigned int stat;
|
|
|
|
int dist, tx, ty, tmin;
|
|
|
|
short damage;
|
2021-11-01 10:30:28 +00:00
|
|
|
SPRITEp sp = &pp->Actor()->s(), hp;
|
2020-03-06 15:49:49 +00:00
|
|
|
USERp hu;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlaySound(DIGI_GASPOP, pp, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Set it just a little to let player know what he just did
|
|
|
|
SetFadeAmt(pp, -30, 1); // White flash
|
|
|
|
|
|
|
|
for (stat = 0; stat < SIZ(StatDamageList); stat++)
|
|
|
|
{
|
2021-11-01 10:30:28 +00:00
|
|
|
SWStatIterator it(StatDamageList[stat]);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:30:28 +00:00
|
|
|
hp = &itActor->s();
|
|
|
|
hu = itActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 10:30:28 +00:00
|
|
|
if (itActor == pp->Actor())
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
DISTANCE(hp->x, hp->y, sp->x, sp->y, dist, tx, ty, tmin);
|
|
|
|
if (dist > 16384) // Flash radius
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_BLOCK))
|
|
|
|
continue;
|
|
|
|
|
2021-11-24 17:35:42 +00:00
|
|
|
if (!FAFcansee(hp->x, hp->y, hp->z, hp->sector(), sp->x, sp->y, sp->z - SPRITEp_SIZE_Z(sp), sp->sector()))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-05 22:00:31 +00:00
|
|
|
damage = GetDamage(itActor, pp->Actor(), DMG_FLASHBOMB);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (hu->sop_parent)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (hu->PlayerP)
|
|
|
|
{
|
|
|
|
// if(hu->PlayerP->NightVision)
|
|
|
|
// {
|
|
|
|
// SetFadeAmt(hu->PlayerP, -200, 1); // Got him with night vision on!
|
|
|
|
// PlayerUpdateHealth(hu->PlayerP, -15); // Hurt eyes
|
|
|
|
// }else
|
|
|
|
if (damage < -70)
|
|
|
|
{
|
|
|
|
int choosesnd = 0;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
choosesnd = RandomRange(MAX_PAIN);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
SetFadeAmt(hu->PlayerP, damage, 1); // White flash
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-05 22:19:57 +00:00
|
|
|
ActorPain(itActor);
|
2021-10-31 08:04:24 +00:00
|
|
|
SpawnFlashBombOnActor(itActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2021-10-29 18:49:57 +00:00
|
|
|
InitFlashBomb(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:35:48 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
unsigned int stat;
|
|
|
|
int dist, tx, ty, tmin;
|
|
|
|
short damage;
|
2021-10-08 08:03:14 +00:00
|
|
|
SPRITEp hp;
|
2020-03-06 15:49:49 +00:00
|
|
|
USERp hu;
|
2015-05-19 21:54:34 +00:00
|
|
|
PLAYERp pp = Player + screenpeek;
|
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GASPOP, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
for (stat = 0; stat < SIZ(StatDamageList); stat++)
|
|
|
|
{
|
2021-11-01 10:35:48 +00:00
|
|
|
SWStatIterator it(StatDamageList[stat]);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:35:48 +00:00
|
|
|
hp = &itActor->s();
|
|
|
|
hu = itActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
DISTANCE(hp->x, hp->y, sp->x, sp->y, dist, tx, ty, tmin);
|
|
|
|
if (dist > 16384) // Flash radius
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_BLOCK))
|
|
|
|
continue;
|
|
|
|
|
2021-11-24 17:35:42 +00:00
|
|
|
if (!FAFcansee(hp->x, hp->y, hp->z, hp->sector(), sp->x, sp->y, sp->z - SPRITEp_SIZE_Z(sp), sp->sector()))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2021-11-05 22:00:31 +00:00
|
|
|
damage = GetDamage(itActor, actor, DMG_FLASHBOMB);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (hu->sop_parent)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (hu->PlayerP)
|
|
|
|
{
|
|
|
|
if (damage < -70)
|
|
|
|
{
|
|
|
|
int choosesnd = 0;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
choosesnd = RandomRange(MAX_PAIN);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlayerSound(PlayerLowHealthPainVocs[choosesnd],v3df_dontpan|v3df_doppler|v3df_follow,pp);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
SetFadeAmt(hu->PlayerP, damage, 1); // White flash
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-11-01 10:35:48 +00:00
|
|
|
if (itActor != actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-05 22:19:57 +00:00
|
|
|
ActorPain(itActor);
|
2021-10-31 08:04:24 +00:00
|
|
|
SpawnFlashBombOnActor(itActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This is a sneaky function to make actors look blinded by flashbomb while using flaming code
|
2021-10-31 08:04:24 +00:00
|
|
|
void SpawnFlashBombOnActor(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 08:04:24 +00:00
|
|
|
if (!actor->hasU()) return;
|
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Forget about burnable sprites
|
2021-10-31 08:04:24 +00:00
|
|
|
if (TEST(sp->extra, SPRX_BURNABLE))
|
|
|
|
return;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
if (actor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 08:04:24 +00:00
|
|
|
if (u->flameActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 08:04:24 +00:00
|
|
|
int sizez = (SPRITEp_SIZE_Z(sp) * 5) >> 2;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
auto np = &u->flameActor->s();
|
|
|
|
auto nu = u->flameActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (nu->Counter >= SPRITEp_SIZE_Z_2_YREPEAT(np, sizez))
|
|
|
|
{
|
|
|
|
// keep flame only slightly bigger than the enemy itself
|
|
|
|
nu->Counter = SPRITEp_SIZE_Z_2_YREPEAT(np, sizez) * 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// increase max size
|
|
|
|
nu->Counter += SPRITEp_SIZE_Z_2_YREPEAT(np, 8 << 8) * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Counter is max size
|
|
|
|
if (nu->Counter >= 230)
|
|
|
|
{
|
|
|
|
// this is far too big
|
|
|
|
nu->Counter = 230;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nu->WaitTics < 2 * 120)
|
|
|
|
nu->WaitTics = 2 * 120; // allow it to grow again
|
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
return;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, FIREBALL_FLAMES, s_FireballFlames, sp->sector(),
|
2021-10-31 08:04:24 +00:00
|
|
|
sp->x, sp->y, sp->z, sp->ang, 0);
|
|
|
|
auto np = &actorNew->s();
|
2021-12-25 18:54:45 +00:00
|
|
|
auto nu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
if (u->flameActor != nullptr)
|
|
|
|
u->flameActor = actorNew;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
np->xrepeat = 16;
|
|
|
|
np->yrepeat = 16;
|
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
if (u->flameActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 08:04:24 +00:00
|
|
|
nu->Counter = SPRITEp_SIZE_Z_2_YREPEAT(np, SPRITEp_SIZE_Z(sp) >> 1) * 4;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
nu->Counter = 0; // max flame size
|
|
|
|
|
|
|
|
np->shade = -40;
|
|
|
|
SET(np->cstat, CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_INVISIBLE);
|
|
|
|
RESET(np->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
|
|
|
|
nu->Radius = 200;
|
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
if (u->flameActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 11:20:03 +00:00
|
|
|
SetAttach(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-31 08:04:24 +00:00
|
|
|
return;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Inventory Caltrops
|
|
|
|
//
|
|
|
|
//////////////////////////////////////////////
|
2021-11-01 10:35:48 +00:00
|
|
|
|
|
|
|
int PlayerInitCaltrops(PLAYERp pp)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:35:48 +00:00
|
|
|
USERp u = pp->Actor()->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
2020-03-06 15:49:55 +00:00
|
|
|
short oclipdist;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlaySound(DIGI_THROW, pp, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-24 20:45:03 +00:00
|
|
|
if (!pp->insector())
|
2019-12-03 09:44:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
nx = pp->posx;
|
|
|
|
ny = pp->posy;
|
|
|
|
nz = pp->posz + pp->bob_z + Z(8);
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto spawnedActor = SpawnActor(STAT_DEAD_ACTOR, CALTROPS, s_Caltrops, pp->cursector(),
|
2021-09-20 06:59:54 +00:00
|
|
|
nx, ny, nz, pp->angle.ang.asbuild(), (CHEMBOMB_VELOCITY + RandomRange(CHEMBOMB_VELOCITY)) / 2);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 10:35:48 +00:00
|
|
|
wp = &spawnedActor->s();
|
|
|
|
wu = spawnedActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// don't throw it as far if crawling
|
|
|
|
if (TEST(pp->Flags, PF_CRAWLING))
|
|
|
|
{
|
2021-11-19 20:47:04 +00:00
|
|
|
wp->xvel -= (wp->xvel >> 2);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
|
2021-11-01 10:35:48 +00:00
|
|
|
SetOwner(pp->Actor(), spawnedActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->yrepeat = 64;
|
|
|
|
wp->xrepeat = 64;
|
|
|
|
wp->shade = -15;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 200;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
// SET(wp->cstat, CSTAT_SPRITE_BLOCK);
|
|
|
|
|
|
|
|
if (TEST(pp->Flags, PF_DIVING) || SpriteInUnderwaterArea(wp))
|
|
|
|
SET(wu->Flags, SPR_UNDERWATER);
|
|
|
|
|
|
|
|
// They go out at different angles
|
2021-09-20 06:59:54 +00:00
|
|
|
// wp->ang = NORM_ANGLE(pp->angle.ang.asbuild() + (RandomRange(50) - 25));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-10-07 07:08:57 +00:00
|
|
|
wp->zvel = -pp->horizon.horiz.asq16() >> 9;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
auto psp = &pp->Actor()->s();
|
|
|
|
oclipdist = psp->clipdist;
|
|
|
|
psp->clipdist = 0;
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->clipdist = 0;
|
|
|
|
|
2021-11-04 23:02:40 +00:00
|
|
|
MissileSetPos(spawnedActor, DoCaltrops, 1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
psp->clipdist = uint8_t(oclipdist);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->clipdist = 80L >> 2;
|
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
|
|
|
|
// adjust xvel according to player velocity
|
|
|
|
wu->xchange += pp->xvect >> 14;
|
|
|
|
wu->ychange += pp->yvect >> 14;
|
|
|
|
|
2021-10-31 14:54:02 +00:00
|
|
|
SetupSpriteForBreak(spawnedActor); // Put Caltrops in the break queue
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 10:50:50 +00:00
|
|
|
int InitCaltrops(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:50:50 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
|
|
|
|
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_THROW, actor, v3df_dontpan | v3df_doppler);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = sp->z;
|
|
|
|
|
|
|
|
// Spawn a shot
|
|
|
|
// Inserting and setting up variables
|
2021-11-24 18:44:43 +00:00
|
|
|
auto spawnedActor = SpawnActor(STAT_DEAD_ACTOR, CALTROPS, s_Caltrops, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
nx, ny, nz, sp->ang, CHEMBOMB_VELOCITY / 2);
|
|
|
|
|
2021-11-01 10:50:50 +00:00
|
|
|
wp = &spawnedActor->s();
|
|
|
|
wu = spawnedActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
|
2021-11-01 10:50:50 +00:00
|
|
|
SetOwner(actor, spawnedActor);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->yrepeat = 64;
|
|
|
|
wp->xrepeat = 64;
|
|
|
|
wp->shade = -15;
|
|
|
|
// !FRANK - clipbox must be <= weapon otherwise can clip thru walls
|
|
|
|
wp->clipdist = sp->clipdist;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 200;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->zvel = short(-RandomRange(100) * HORIZ_MULT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// wp->clipdist = 80L>>2;
|
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
|
2021-10-31 14:54:02 +00:00
|
|
|
SetupSpriteForBreak(spawnedActor); // Put Caltrops in the break queue
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 10:50:50 +00:00
|
|
|
int InitPhosphorus(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:50:50 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
2020-03-06 15:49:49 +00:00
|
|
|
short daang;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_FIREBALL1, actor, v3df_follow);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = sp->z;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
daang = NORM_ANGLE(RandomRange(2048));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// Spawn a shot
|
|
|
|
// Inserting and setting up variables
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_SKIP4, FIREBALL1, s_Phosphorus, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
nx, ny, nz, daang, CHEMBOMB_VELOCITY/3);
|
|
|
|
|
2021-11-01 10:50:50 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
wp->hitag = LUMINOUS; // Always full brightness
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
// !Frank - don't do translucent
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
// SET(wp->cstat, CSTAT_SPRITE_TRANSLUCENT|CSTAT_SPRITE_YCENTER);
|
|
|
|
wp->shade = -128;
|
|
|
|
|
|
|
|
wp->yrepeat = 64;
|
|
|
|
wp->xrepeat = 64;
|
|
|
|
wp->shade = -15;
|
|
|
|
// !FRANK - clipbox must be <= weapon otherwise can clip thru walls
|
|
|
|
if (sp->clipdist > 0)
|
|
|
|
wp->clipdist = sp->clipdist-1;
|
|
|
|
else
|
|
|
|
wp->clipdist = sp->clipdist;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 600;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->zvel = short(-RandomRange(100) * HORIZ_MULT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = (wp->zvel >> 1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 10:57:51 +00:00
|
|
|
int InitBloodSpray(DSWActor* actor, bool dogib, short velocity)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 10:57:51 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
|
|
|
SPRITEp wp;
|
|
|
|
int nx, ny, nz;
|
2020-03-06 15:49:49 +00:00
|
|
|
short i, cnt, ang, vel, rnd;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (dogib)
|
2021-09-20 06:59:54 +00:00
|
|
|
cnt = RandomRange(3)+1;
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
|
|
|
cnt = 1;
|
|
|
|
|
|
|
|
//if(dogib)
|
|
|
|
// {
|
2021-09-20 06:59:54 +00:00
|
|
|
rnd = RandomRange(1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
if (rnd > 650)
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GIBS1, actor, v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
else if (rnd > 350)
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GIBS2, actor, v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_GIBS3, actor, v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
// }
|
|
|
|
|
|
|
|
ang = sp->ang;
|
|
|
|
vel = velocity;
|
|
|
|
|
|
|
|
for (i=0; i<cnt; i++)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (velocity == -1)
|
2021-09-20 06:59:54 +00:00
|
|
|
vel = 105+RandomRange(320);
|
2015-05-19 21:54:34 +00:00
|
|
|
else if (velocity == -2)
|
2021-09-20 06:59:54 +00:00
|
|
|
vel = 105+RandomRange(100);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (dogib)
|
2021-09-20 06:59:54 +00:00
|
|
|
ang = NORM_ANGLE(ang + 512 + RandomRange(200));
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-09-20 06:59:54 +00:00
|
|
|
ang = NORM_ANGLE(ang+1024+256 - RandomRange(256));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = SPRITEp_TOS(sp)-20;
|
|
|
|
|
|
|
|
// Spawn a shot
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_MISSILE, GOREDrip, s_BloodSprayChunk, sp->sector(),
|
2015-05-19 21:54:34 +00:00
|
|
|
nx, ny, nz, ang, vel*2);
|
|
|
|
|
2021-11-01 10:57:51 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SET(wu->Flags, SPR_XFLIP_TOGGLE);
|
|
|
|
if (dogib)
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
else
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER | CSTAT_SPRITE_INVISIBLE);
|
|
|
|
wp->shade = -12;
|
|
|
|
|
2021-11-01 10:57:51 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->yrepeat = 64-RandomRange(35);
|
|
|
|
wp->xrepeat = 64-RandomRange(35);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->shade = -15;
|
|
|
|
wp->clipdist = sp->clipdist;
|
|
|
|
wu->WeaponNum = u->WeaponNum;
|
|
|
|
wu->Radius = 600;
|
|
|
|
wu->ceiling_dist = Z(3);
|
|
|
|
wu->floor_dist = Z(3);
|
|
|
|
wu->Counter = 0;
|
|
|
|
|
2021-09-20 06:59:54 +00:00
|
|
|
wp->zvel = short((-10 - RandomRange(50)) * HORIZ_MULT);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel >> 1;
|
|
|
|
|
|
|
|
if (!GlobalSkipZrange)
|
2021-11-03 16:47:13 +00:00
|
|
|
DoActorZrange(actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
int BloodSprayFall(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
actor->s().z += 1500;
|
2015-05-19 21:54:34 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////// DEATHFLAG! ////////////////////////////////////////////////////////////////
|
|
|
|
// Rules: Run to an enemy flag, run over it an it will stick to you.
|
|
|
|
// The goal is to run the enemy's flag back to your startpoint.
|
|
|
|
// If an enemy flag touches a friendly start sector, then the opposing team explodes and
|
|
|
|
// your team wins and the level restarts.
|
|
|
|
// Once you pick up a flag, you have 30 seconds to score, otherwise, the flag detonates
|
|
|
|
// an explosion, killing you and anyone in the vicinity, and you don't score.
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Update the scoreboard for team color that just scored.
|
2021-11-01 11:04:55 +00:00
|
|
|
void DoFlagScore(int16_t pal)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp;
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
SWStatIterator it(STAT_DEFAULT);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (sp->picnum < 1900 || sp->picnum > 1999)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sp->pal == pal)
|
|
|
|
sp->picnum++; // Increment the counter
|
|
|
|
|
|
|
|
if (sp->picnum > 1999)
|
|
|
|
sp->picnum = 1900; // Roll it over if you must
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
DSWActor* DoFlagRangeTest(DSWActor* actor, int range)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
SPRITEp wp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
SPRITEp sp;
|
|
|
|
unsigned int stat;
|
|
|
|
int dist, tx, ty;
|
|
|
|
int tmin;
|
|
|
|
|
|
|
|
for (stat = 0; stat < SIZ(StatDamageList); stat++)
|
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
SWStatIterator it(StatDamageList[stat]);
|
|
|
|
while (auto itActor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
sp = &itActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
DISTANCE(sp->x, sp->y, wp->x, wp->y, dist, tx, ty, tmin);
|
|
|
|
if (dist > range)
|
|
|
|
continue;
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
if (actor == itActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!TEST(sp->cstat, CSTAT_SPRITE_BLOCK))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!TEST(sp->extra, SPRX_PLAYER_OR_ENEMY))
|
|
|
|
continue;
|
|
|
|
|
2021-11-24 17:35:42 +00:00
|
|
|
if (!FAFcansee(sp->x, sp->y, sp->z, sp->sector(), wp->x, wp->y, wp->z, wp->sector()))
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
|
2019-12-26 06:28:16 +00:00
|
|
|
dist = FindDistance3D(wp->x - sp->x, wp->y - sp->y, wp->z - sp->z);
|
2015-05-19 21:54:34 +00:00
|
|
|
if (dist > range)
|
|
|
|
continue;
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
return itActor;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
return nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
int DoCarryFlag(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 09:48:45 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
const int FLAG_DETONATE_STATE = 99;
|
2021-11-01 11:13:24 +00:00
|
|
|
auto fown = u->flagOwnerActor;
|
|
|
|
if (!fown) return 0;
|
|
|
|
SPRITEp fp = &fown->s();
|
|
|
|
USERp fu = fown->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
// if no Owner then die
|
2021-10-31 11:20:03 +00:00
|
|
|
if (u->attachActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 11:20:03 +00:00
|
|
|
SPRITEp ap = &u->attachActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 09:48:45 +00:00
|
|
|
vec3_t pos = { ap->x, ap->y, SPRITEp_MID(ap) };
|
|
|
|
SetActorZ(actor, &pos);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = NORM_ANGLE(ap->ang + 1536);
|
|
|
|
}
|
|
|
|
|
|
|
|
// not activated yet
|
|
|
|
if (!TEST(u->Flags, SPR_ACTIVE))
|
|
|
|
{
|
|
|
|
if ((u->WaitTics -= (MISSILEMOVETICS * 2)) > 0)
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// activate it
|
|
|
|
u->WaitTics = SEC(30); // You have 30 seconds to get it to
|
|
|
|
// scorebox
|
|
|
|
u->Counter2 = 0;
|
|
|
|
SET(u->Flags, SPR_ACTIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
// limit the number of times DoFlagRangeTest is called
|
|
|
|
u->Counter++;
|
|
|
|
if (u->Counter > 1)
|
|
|
|
u->Counter = 0;
|
|
|
|
|
|
|
|
if (!u->Counter)
|
|
|
|
{
|
|
|
|
// not already in detonate state
|
|
|
|
if (u->Counter2 < FLAG_DETONATE_STATE)
|
|
|
|
{
|
2021-10-31 11:20:03 +00:00
|
|
|
SPRITEp ap = &u->attachActor->s();
|
|
|
|
USERp au = u->attachActor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (!au || au->Health <= 0)
|
|
|
|
{
|
|
|
|
u->Counter2 = FLAG_DETONATE_STATE;
|
|
|
|
u->WaitTics = SEC(1) / 2;
|
|
|
|
}
|
|
|
|
// if in score box, score.
|
2021-11-24 22:16:28 +00:00
|
|
|
if (ap->sector()->hitag == 9000 && ap->sector()->lotag == ap->pal
|
2015-05-19 21:54:34 +00:00
|
|
|
&& ap->pal != sp->pal)
|
|
|
|
{
|
2021-11-01 11:13:24 +00:00
|
|
|
if (fown != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:13:24 +00:00
|
|
|
if (fp->lotag) // Trigger everything if there is a lotag
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, fp->lotag, ON);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
if (!TEST_BOOL1(fp))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_BIGITEM, u->attachActor, v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
DoFlagScore(ap->pal);
|
|
|
|
if (SP_TAG5(fp) > 0)
|
|
|
|
{
|
2015-05-19 22:04:06 +00:00
|
|
|
fu->filler++;
|
|
|
|
if (fu->filler >= SP_TAG5(fp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:04:06 +00:00
|
|
|
fu->filler = 0;
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, SP_TAG6(fp), ON);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor); // Kill the flag, you scored!
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Time's up! Move directly to detonate state
|
|
|
|
u->Counter2 = FLAG_DETONATE_STATE;
|
|
|
|
u->WaitTics = SEC(1) / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
u->WaitTics -= (MISSILEMOVETICS * 2);
|
|
|
|
|
|
|
|
switch (u->Counter2)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
if (u->WaitTics < SEC(30))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (u->WaitTics < SEC(20))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (u->WaitTics < SEC(10))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (u->WaitTics < SEC(5))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
if (u->WaitTics < SEC(4))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
if (u->WaitTics < SEC(3))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
if (u->WaitTics < SEC(2))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2 = FLAG_DETONATE_STATE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FLAG_DETONATE_STATE:
|
|
|
|
// start frantic beeping
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_MINEBEEP, actor, v3df_dontpan);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->Counter2++;
|
|
|
|
break;
|
|
|
|
case FLAG_DETONATE_STATE + 1:
|
2021-11-04 23:18:16 +00:00
|
|
|
SpawnGrenadeExp(actor);
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 11:25:35 +00:00
|
|
|
int DoCarryFlagNoDet(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 11:25:35 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2021-10-08 08:03:14 +00:00
|
|
|
|
2021-10-31 11:20:03 +00:00
|
|
|
SPRITEp ap = &u->attachActor->s();
|
|
|
|
USERp au = u->attachActor->u();
|
2021-11-01 11:13:24 +00:00
|
|
|
auto fown = u->flagOwnerActor;
|
|
|
|
if (!fown) return 0;
|
|
|
|
SPRITEp fp = &fown->s();
|
|
|
|
USERp fu = fown->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
|
2021-11-01 11:13:24 +00:00
|
|
|
if (u->flagOwnerActor != nullptr)
|
2021-11-01 11:25:35 +00:00
|
|
|
fu->WaitTics = 30 * 120; // Keep setting respawn tics so it won't respawn
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:58:02 +00:00
|
|
|
// if no Owner then die
|
2021-10-31 11:20:03 +00:00
|
|
|
if (u->attachActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 11:20:03 +00:00
|
|
|
SPRITEp ap = &u->attachActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:25:35 +00:00
|
|
|
vec3_t pos = { ap->x, ap->y, SPRITEp_MID(ap) };
|
|
|
|
SetActorZ(actor, &pos);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->ang = NORM_ANGLE(ap->ang + 1536);
|
|
|
|
sp->z = ap->z - DIV2(SPRITEp_SIZE_Z(ap));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!au || au->Health <= 0)
|
|
|
|
{
|
2021-11-01 11:13:24 +00:00
|
|
|
if (u->flagOwnerActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
fu->WaitTics = 0; // Tell it to respawn
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if in score box, score.
|
2021-11-24 22:16:28 +00:00
|
|
|
if (ap->sector()->hitag == 9000 && ap->sector()->lotag == ap->pal
|
2015-05-19 21:54:34 +00:00
|
|
|
&& ap->pal != sp->pal)
|
|
|
|
{
|
2021-11-01 11:13:24 +00:00
|
|
|
if (u->flagOwnerActor != nullptr)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:13:24 +00:00
|
|
|
if (fp->lotag) // Trigger everything if there is a lotag
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, fp->lotag, ON);
|
2015-05-19 21:54:34 +00:00
|
|
|
fu->WaitTics = 0; // Tell it to respawn
|
|
|
|
}
|
|
|
|
if (!TEST_BOOL1(fp))
|
|
|
|
{
|
2021-11-02 22:08:59 +00:00
|
|
|
PlaySound(DIGI_BIGITEM, u->attachActor, v3df_none);
|
2015-05-19 21:54:34 +00:00
|
|
|
DoFlagScore(ap->pal);
|
|
|
|
if (SP_TAG5(fp) > 0)
|
|
|
|
{
|
2015-05-19 22:04:06 +00:00
|
|
|
fu->filler++;
|
|
|
|
if (fu->filler >= SP_TAG5(fp))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:04:06 +00:00
|
|
|
fu->filler = 0;
|
2021-07-10 12:25:18 +00:00
|
|
|
DoMatchEverything(nullptr, SP_TAG6(fp), ON);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-30 20:44:16 +00:00
|
|
|
SetSuicide(actor); // Kill the flag, you scored!
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
int SetCarryFlag(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// stuck
|
|
|
|
SET(u->Flags, SPR_BOUNCE);
|
|
|
|
// not yet active for 1 sec
|
|
|
|
// RESET(u->Flags, SPR_ACTIVE);
|
|
|
|
// u->WaitTics = SEC(3);
|
|
|
|
SET(sp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
u->Counter = 0;
|
2021-11-01 11:04:55 +00:00
|
|
|
change_actor_stat(actor, STAT_ITEM);
|
2015-05-19 21:54:34 +00:00
|
|
|
if (sp->hitag == 1)
|
2021-11-01 11:04:55 +00:00
|
|
|
ChangeState(actor, s_CarryFlagNoDet);
|
2015-05-19 21:54:34 +00:00
|
|
|
else
|
2021-11-01 11:04:55 +00:00
|
|
|
ChangeState(actor, s_CarryFlag);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
int DoFlag(DSWActor* actor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-29 18:49:57 +00:00
|
|
|
USER* u = actor->u();
|
2021-11-01 11:04:55 +00:00
|
|
|
SPRITEp sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
auto hitActor = DoFlagRangeTest(actor, 1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
if (hitActor)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:04:55 +00:00
|
|
|
SPRITEp hsp = &hitActor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:04:55 +00:00
|
|
|
SetCarryFlag(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// check to see if sprite is player or enemy
|
|
|
|
if (TEST(hsp->extra, SPRX_PLAYER_OR_ENEMY))
|
|
|
|
{
|
|
|
|
// attach weapon to sprite
|
|
|
|
RESET(sp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
2021-10-31 11:20:03 +00:00
|
|
|
SetAttach(hitActor, actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
u->sz = hsp->z - DIV2(SPRITEp_SIZE_Z(hsp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-01 11:25:35 +00:00
|
|
|
int SpawnShell(DSWActor* actor, int ShellNum)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-11-01 11:25:35 +00:00
|
|
|
USERp u = actor->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
USERp wu;
|
2021-11-01 11:25:35 +00:00
|
|
|
SPRITEp sp = &actor->s(), wp;
|
2015-05-19 21:54:34 +00:00
|
|
|
int nx, ny, nz;
|
2021-11-01 11:25:35 +00:00
|
|
|
short id=0,velocity=0; STATEp p=nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
extern STATE s_UziShellShrap[];
|
|
|
|
extern STATE s_ShotgunShellShrap[];
|
|
|
|
|
|
|
|
|
|
|
|
nx = sp->x;
|
|
|
|
ny = sp->y;
|
|
|
|
nz = DIV2(SPRITEp_TOS(sp)+ SPRITEp_BOS(sp));
|
|
|
|
|
|
|
|
switch (ShellNum)
|
|
|
|
{
|
|
|
|
case -2:
|
|
|
|
case -3:
|
|
|
|
id = UZI_SHELL;
|
|
|
|
p = s_UziShellShrap;
|
2021-09-20 06:59:54 +00:00
|
|
|
velocity = 1500 + RandomRange(1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
case -4:
|
|
|
|
id = SHOT_SHELL;
|
|
|
|
p = s_ShotgunShellShrap;
|
2021-09-20 06:59:54 +00:00
|
|
|
velocity = 2000 + RandomRange(1000);
|
2015-05-19 21:54:34 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-24 18:44:43 +00:00
|
|
|
auto actorNew = SpawnActor(STAT_SKIP4, id, p, sp->sector(), nx, ny, nz, sp->ang, 64);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-11-01 11:25:35 +00:00
|
|
|
wp = &actorNew->s();
|
|
|
|
wu = actorNew->u();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
wp->zvel = -(velocity);
|
|
|
|
|
|
|
|
if (u->PlayerP)
|
|
|
|
{
|
2021-01-04 11:16:09 +00:00
|
|
|
wp->z += xs_CRoundToInt(-MulScaleF(u->PlayerP->horizon.horiz.asq16(), HORIZ_MULT / 3., 16));
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (wu->ID)
|
|
|
|
{
|
|
|
|
case UZI_SHELL:
|
|
|
|
wp->z -= Z(13);
|
|
|
|
|
|
|
|
if (ShellNum == -3)
|
|
|
|
{
|
|
|
|
wp->ang = sp->ang;
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,2500);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang-512);
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,1000); // Was 1500
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang+712);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wp->ang = sp->ang;
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,2500);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang+512);
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,1500);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang-128);
|
|
|
|
}
|
|
|
|
wp->ang += (RANDOM_P2(128<<5)>>5) - DIV2(128);
|
|
|
|
wp->ang = NORM_ANGLE(wp->ang);
|
|
|
|
|
|
|
|
// Set the shell number
|
|
|
|
wu->ShellNum = ShellCount;
|
|
|
|
wp->yrepeat = wp->xrepeat = 13;
|
|
|
|
break;
|
|
|
|
case SHOT_SHELL:
|
|
|
|
wp->z -= Z(13);
|
|
|
|
wp->ang = sp->ang;
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,2500);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang+512);
|
2021-11-04 22:27:04 +00:00
|
|
|
HelpMissileLateral(actorNew,1300);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->ang = NORM_ANGLE(wp->ang-128-64);
|
|
|
|
wp->ang += (RANDOM_P2(128<<5)>>5) - DIV2(128);
|
|
|
|
wp->ang = NORM_ANGLE(wp->ang);
|
|
|
|
|
|
|
|
// Set the shell number
|
|
|
|
wu->ShellNum = ShellCount;
|
|
|
|
wp->yrepeat = wp->xrepeat = 18;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-11-01 11:25:35 +00:00
|
|
|
SetOwner(actor, actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
wp->shade = -15;
|
|
|
|
wu->ceiling_dist = Z(1);
|
|
|
|
wu->floor_dist = Z(1);
|
|
|
|
wu->Counter = 0;
|
|
|
|
SET(wp->cstat, CSTAT_SPRITE_YCENTER);
|
|
|
|
RESET(wp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
|
|
|
|
RESET(wu->Flags, SPR_BOUNCE|SPR_UNDERWATER); // Make em' bounce
|
|
|
|
|
|
|
|
wu->xchange = MOVEx(wp->xvel, wp->ang);
|
|
|
|
wu->ychange = MOVEy(wp->xvel, wp->ang);
|
|
|
|
wu->zchange = wp->zvel;
|
|
|
|
//if (TEST(u->PlayerP->Flags, PF_DIVING) || SpriteInUnderwaterArea(wp))
|
|
|
|
// SET(wu->Flags, SPR_UNDERWATER);
|
|
|
|
wu->jump_speed = 200;
|
2021-09-20 06:59:54 +00:00
|
|
|
wu->jump_speed += RandomRange(400);
|
2015-05-19 21:54:34 +00:00
|
|
|
wu->jump_speed = -wu->jump_speed;
|
|
|
|
|
2021-10-29 21:03:47 +00:00
|
|
|
DoBeginJump(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
wu->jump_grav = ACTOR_GRAVITY;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "saveable.h"
|
|
|
|
|
|
|
|
static saveable_data saveable_jweapon_data[] =
|
|
|
|
{
|
|
|
|
SAVE_DATA(s_BloodSpray),
|
|
|
|
SAVE_DATA(s_PhosphorExp),
|
|
|
|
SAVE_DATA(s_NukeMushroom),
|
|
|
|
SAVE_DATA(s_RadiationCloud),
|
|
|
|
SAVE_DATA(s_ChemBomb),
|
|
|
|
SAVE_DATA(s_Caltrops),
|
|
|
|
SAVE_DATA(s_CaltropsStick),
|
|
|
|
SAVE_DATA(s_CarryFlag),
|
|
|
|
SAVE_DATA(s_CarryFlagNoDet),
|
|
|
|
SAVE_DATA(s_Flag),
|
|
|
|
SAVE_DATA(s_Phosphorus),
|
|
|
|
SAVE_DATA(s_BloodSprayChunk),
|
|
|
|
SAVE_DATA(s_BloodSprayDrip),
|
|
|
|
};
|
|
|
|
|
|
|
|
saveable_module saveable_jweapon =
|
|
|
|
{
|
|
|
|
// code
|
2021-07-10 12:25:18 +00:00
|
|
|
nullptr,0,
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// data
|
|
|
|
saveable_jweapon_data,
|
|
|
|
SIZ(saveable_jweapon_data)
|
|
|
|
};
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|