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"
|
|
|
|
|
2020-05-29 00:32:53 +00:00
|
|
|
#include "gamecontrol.h"
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "names2.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "tags.h"
|
|
|
|
#include "break.h"
|
|
|
|
#include "sprite.h"
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#define QUAKE_Match(sp) (SP_TAG2(sp))
|
|
|
|
#define QUAKE_Zamt(sp) (SP_TAG3(sp))
|
|
|
|
#define QUAKE_Radius(sp) (SP_TAG4(sp))
|
|
|
|
#define QUAKE_Duration(sp) (SP_TAG5(sp))
|
|
|
|
#define QUAKE_WaitSecs(sp) (SP_TAG6(sp))
|
|
|
|
#define QUAKE_AngAmt(sp) (SP_TAG7(sp))
|
|
|
|
#define QUAKE_PosAmt(sp) (SP_TAG8(sp))
|
|
|
|
#define QUAKE_RandomTest(sp) (SP_TAG9(sp))
|
|
|
|
#define QUAKE_WaitTics(sp) (SP_TAG13(sp))
|
|
|
|
|
|
|
|
#define QUAKE_TestDontTaper(sp) (TEST_BOOL1(sp))
|
|
|
|
#define QUAKE_KillAfterQuake(sp) (TEST_BOOL2(sp))
|
|
|
|
// only for timed quakes
|
|
|
|
#define QUAKE_WaitForTrigger(sp) (TEST_BOOL3(sp))
|
|
|
|
|
|
|
|
short CopyQuakeSpotToOn(SPRITEp sp)
|
|
|
|
{
|
2021-10-31 18:07:50 +00:00
|
|
|
auto actorNew = InsertActor(sp->sectnum, STAT_QUAKE_SPOT);
|
|
|
|
auto np = &actorNew->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
memcpy(np, sp, sizeof(SPRITE));
|
|
|
|
|
|
|
|
np->sectnum = sp->sectnum;
|
|
|
|
np->statnum = sp->statnum;
|
|
|
|
|
|
|
|
np->cstat = 0;
|
|
|
|
np->extra = 0;
|
2021-10-31 18:07:50 +00:00
|
|
|
ClearOwner(actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 18:07:50 +00:00
|
|
|
change_actor_stat(actorNew, STAT_QUAKE_ON);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
QUAKE_Duration(np) *= 120;
|
|
|
|
|
2021-10-31 18:07:50 +00:00
|
|
|
return actorNew->GetSpriteIndex();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoQuakeMatch(short match)
|
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp sp;
|
|
|
|
|
2020-10-15 15:30:55 +00:00
|
|
|
StatIterator it(STAT_QUAKE_SPOT);
|
|
|
|
while ((i = it.NextIndex()) >= 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
sp = &sprite[i];
|
|
|
|
|
|
|
|
if (QUAKE_Match(sp) == match)
|
|
|
|
{
|
2015-05-19 22:07:54 +00:00
|
|
|
if ((int16_t)QUAKE_WaitTics(sp) > 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// its not waiting any more
|
|
|
|
RESET_BOOL3(sp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CopyQuakeSpotToOn(sp);
|
|
|
|
if (QUAKE_KillAfterQuake(sp))
|
|
|
|
{
|
|
|
|
KillSprite(i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProcessQuakeOn(void)
|
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp sp;
|
|
|
|
|
2020-10-15 15:30:55 +00:00
|
|
|
StatIterator it(STAT_QUAKE_ON);
|
|
|
|
while ((i = it.NextIndex()) >= 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
sp = &sprite[i];
|
|
|
|
|
|
|
|
// get rid of quake when timer runs out
|
|
|
|
QUAKE_Duration(sp) -= synctics*4;
|
|
|
|
if (QUAKE_Duration(sp) < 0)
|
|
|
|
{
|
|
|
|
KillSprite(i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProcessQuakeSpot(void)
|
|
|
|
{
|
|
|
|
int rand_test;
|
|
|
|
|
|
|
|
// check timed quakes and random quakes
|
2021-10-31 17:10:59 +00:00
|
|
|
SWStatIterator it(STAT_QUAKE_SPOT);
|
|
|
|
while (auto actor = it.Next())
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2021-10-31 17:10:59 +00:00
|
|
|
auto sp = &actor->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// not a timed quake
|
|
|
|
if (!QUAKE_WaitSecs(sp))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// don't process unless triggered
|
|
|
|
if (QUAKE_WaitForTrigger(sp))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// spawn a quake if time is up
|
|
|
|
//QUAKE_WaitTics(sp) -= 4*synctics;
|
|
|
|
SET_SP_TAG13(sp, (QUAKE_WaitTics(sp)-4*synctics));
|
2015-05-19 22:07:54 +00:00
|
|
|
if ((int16_t)QUAKE_WaitTics(sp) < 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
// reset timer - add in Duration of quake
|
2021-10-31 17:10:59 +00:00
|
|
|
SET_SP_TAG13(sp, (((QUAKE_WaitSecs(sp)*10) + QUAKE_Duration(sp)) * 120));
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// spawn a quake if condition is met
|
|
|
|
rand_test = QUAKE_RandomTest(sp);
|
|
|
|
// wrong - all quakes need to happen at the same time on all computerssg
|
|
|
|
//if (!rand_test || (rand_test && STD_RANDOM_RANGE(128) < rand_test))
|
2021-09-20 06:59:54 +00:00
|
|
|
if (!rand_test || (rand_test && RandomRange(128) < rand_test))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
CopyQuakeSpotToOn(sp);
|
|
|
|
// kill quake spot if needed
|
|
|
|
if (QUAKE_KillAfterQuake(sp))
|
|
|
|
{
|
2021-10-31 17:10:59 +00:00
|
|
|
DeleteNoSoundOwner(actor);
|
|
|
|
KillActor(actor);
|
2015-05-19 21:54:34 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuakeViewChange(PLAYERp pp, int *z_diff, int *x_diff, int *y_diff, short *ang_diff)
|
|
|
|
{
|
2020-10-15 15:45:07 +00:00
|
|
|
int i;
|
2015-05-19 21:54:34 +00:00
|
|
|
SPRITEp sp;
|
2021-07-10 12:25:18 +00:00
|
|
|
SPRITEp save_sp = nullptr;
|
2015-05-19 21:54:34 +00:00
|
|
|
int dist,save_dist = 999999;
|
|
|
|
int dist_diff, scale_value;
|
|
|
|
int ang_amt;
|
|
|
|
int radius;
|
|
|
|
int pos_amt;
|
|
|
|
|
|
|
|
*z_diff = 0;
|
|
|
|
*x_diff = 0;
|
|
|
|
*y_diff = 0;
|
|
|
|
*ang_diff = 0;
|
|
|
|
|
2020-05-29 00:32:53 +00:00
|
|
|
if (paused)
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// find the closest quake - should be a strength value
|
2020-10-15 15:30:55 +00:00
|
|
|
StatIterator it(STAT_QUAKE_ON);
|
|
|
|
while ((i = it.NextIndex()) >= 0)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
sp = &sprite[i];
|
|
|
|
|
2019-12-26 06:28:16 +00:00
|
|
|
dist = FindDistance3D(pp->posx - sp->x, pp->posy - sp->y, pp->posz - sp->z);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// shake whole level
|
|
|
|
if (QUAKE_TestDontTaper(sp))
|
|
|
|
{
|
|
|
|
save_dist = dist;
|
|
|
|
save_sp = sp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dist < save_dist)
|
|
|
|
{
|
|
|
|
save_dist = dist;
|
|
|
|
save_sp = sp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!save_sp)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
sp = save_sp;
|
|
|
|
|
|
|
|
radius = QUAKE_Radius(sp) * 8L;
|
|
|
|
if (save_dist > radius)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*z_diff = Z(STD_RANDOM_RANGE(QUAKE_Zamt(sp)) - (QUAKE_Zamt(sp)/2));
|
|
|
|
|
|
|
|
ang_amt = QUAKE_AngAmt(sp) * 4L;
|
|
|
|
*ang_diff = STD_RANDOM_RANGE(ang_amt) - (ang_amt/2);
|
|
|
|
|
|
|
|
pos_amt = QUAKE_PosAmt(sp) * 4L;
|
|
|
|
*x_diff = STD_RANDOM_RANGE(pos_amt) - (pos_amt/2);
|
|
|
|
*y_diff = STD_RANDOM_RANGE(pos_amt) - (pos_amt/2);
|
|
|
|
|
|
|
|
if (!QUAKE_TestDontTaper(sp))
|
|
|
|
{
|
|
|
|
// scale values from epicenter
|
|
|
|
dist_diff = radius - save_dist;
|
2021-01-04 11:51:41 +00:00
|
|
|
scale_value = DivScale(dist_diff, radius, 16);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-01-04 11:36:54 +00:00
|
|
|
*z_diff = MulScale(*z_diff, scale_value, 16);
|
|
|
|
*ang_diff = MulScale(*ang_diff, scale_value, 16);
|
|
|
|
*x_diff = MulScale(*x_diff, scale_value, 16);
|
|
|
|
*y_diff = MulScale(*y_diff, scale_value, 16);
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SpawnQuake(short sectnum, int x, int y, int z,
|
|
|
|
short tics, short amt, int radius)
|
|
|
|
{
|
|
|
|
|
2021-10-31 18:07:50 +00:00
|
|
|
auto actorNew = InsertActor(sectnum, STAT_QUAKE_ON);
|
|
|
|
auto sp = &actorNew->s();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
sp->x = x;
|
|
|
|
sp->y = y;
|
|
|
|
sp->z = z;
|
|
|
|
sp->cstat = 0;
|
2021-10-31 18:07:50 +00:00
|
|
|
ClearOwner(actorNew);
|
2015-05-19 21:54:34 +00:00
|
|
|
sp->extra = 0;
|
|
|
|
|
|
|
|
QUAKE_Match(sp) = -1;
|
2021-05-12 14:50:20 +00:00
|
|
|
QUAKE_Zamt(sp) = uint8_t(amt);
|
2015-05-19 21:54:34 +00:00
|
|
|
QUAKE_Radius(sp) = radius/8;
|
|
|
|
QUAKE_Duration(sp) = tics;
|
|
|
|
QUAKE_AngAmt(sp) = 8;
|
|
|
|
QUAKE_PosAmt(sp) = 0;
|
|
|
|
|
2019-12-18 10:09:01 +00:00
|
|
|
PlaySound(DIGI_ERUPTION, sp, v3df_follow|v3df_dontpan);
|
2021-10-31 18:07:50 +00:00
|
|
|
Set3DSoundOwner(actorNew->GetSpriteIndex());
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2021-10-31 18:07:50 +00:00
|
|
|
return actorNew->GetSpriteIndex();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-09 18:32:24 +00:00
|
|
|
bool
|
2015-05-19 21:54:34 +00:00
|
|
|
SetQuake(PLAYERp pp, short tics, short amt)
|
|
|
|
{
|
|
|
|
SpawnQuake(pp->cursectnum, pp->posx, pp->posy, pp->posz, tics, amt, 30000);
|
2020-09-09 17:52:52 +00:00
|
|
|
return false;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-05-19 21:58:29 +00:00
|
|
|
SetExpQuake(int16_t Weapon)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp = &sprite[Weapon];
|
|
|
|
|
|
|
|
SpawnQuake(sp->sectnum, sp->x, sp->y, sp->z, 40, 4, 20000); // !JIM! was 8, 40000
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-05-19 21:58:29 +00:00
|
|
|
SetGunQuake(int16_t SpriteNum)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp = &sprite[SpriteNum];
|
|
|
|
|
|
|
|
SpawnQuake(sp->sectnum, sp->x, sp->y, sp->z, 40, 8, 40000);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
SetPlayerQuake(PLAYERp pp)
|
|
|
|
{
|
|
|
|
SpawnQuake(pp->cursectnum, pp->posx, pp->posy, pp->posz, 40, 8, 40000);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-05-19 21:58:29 +00:00
|
|
|
SetNuclearQuake(int16_t Weapon)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp = &sprite[Weapon];
|
|
|
|
|
|
|
|
SpawnQuake(sp->sectnum, sp->x, sp->y, sp->z, 400, 8, 64000);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-05-19 21:58:29 +00:00
|
|
|
SetSumoQuake(int16_t SpriteNum)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp = &sprite[SpriteNum];
|
|
|
|
|
|
|
|
SpawnQuake(sp->sectnum, sp->x, sp->y, sp->z, 120, 4, 20000);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-05-19 21:58:29 +00:00
|
|
|
SetSumoFartQuake(int16_t SpriteNum)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
SPRITEp sp = &sprite[SpriteNum];
|
|
|
|
|
|
|
|
SpawnQuake(sp->sectnum, sp->x, sp->y, sp->z, 60, 4, 4000);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|