avp/3dc/avp/STRATDEF.C
Rebellion Developments 218ca90543 Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from:
https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code

All text files were converted to Unix format.
2019-08-19 05:45:17 +02:00

748 lines
No EOL
18 KiB
C

#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "dynblock.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "bh_alien.h"
#include "bh_marin.h"
#include "bh_xeno.h"
#include "bh_corpse.h"
#include "bh_debri.h"
#include "pldnet.h"
/*
this attaches runtime and precompiled object
strategyblocks
*/
/*** exported globals *************/
int NumActiveStBlocks;
STRATEGYBLOCK *ActiveStBlockList[maxstblocks];
/*** static globals ***************/
static int NumFreeStBlocks;
static STRATEGYBLOCK *FreeStBlockList[maxstblocks];
static STRATEGYBLOCK **FreeStBlockListPtr = &FreeStBlockList[maxstblocks-1];
STRATEGYBLOCK FreeStBlockData[maxstblocks];
static STRATEGYBLOCK **ActiveStBlockListPtr = &ActiveStBlockList[0];
unsigned int IncrementalSBname;
/**** improted globals ************/
extern int cosine[], sine[];
/*
Support functions for Strategy Blocks
*/
void InitialiseStrategyBlocks(void)
{
STRATEGYBLOCK *FreeBlkPtr = &FreeStBlockData[0];
FreeStBlockListPtr = &FreeStBlockList[maxstblocks-1];
for(NumFreeStBlocks=0; NumFreeStBlocks < maxstblocks; NumFreeStBlocks++)
{
FreeStBlockList[NumFreeStBlocks] = FreeBlkPtr;
FreeBlkPtr->SBflags.destroyed_but_preserved=0;
#if debug
FreeBlkPtr->SBIsValid = 0;
#endif
FreeBlkPtr++;
}
/* KJL 17:31:18 11/13/96 - seems like a logical place to initialise dynamics blocks */
InitialiseDynamicsBlocks();
NumActiveStBlocks = 0;
ActiveStBlockListPtr = &ActiveStBlockList[0];
IncrementalSBname=0;
}
STRATEGYBLOCK* AllocateStrategyBlock(void)
{
STRATEGYBLOCK *FreeBlkPtr = 0; /* Default to null ptr */
int *sptr;
int i;
if(NumFreeStBlocks)
{
FreeBlkPtr = *FreeStBlockListPtr--;
NumFreeStBlocks--; /* One less free block */
/* Clear the block */
sptr = (int *)FreeBlkPtr;
for(i = sizeof(STRATEGYBLOCK)/4; i!=0; i--)
{
*sptr++ = 0;
}
}
return(FreeBlkPtr);
}
void DeallocateStrategyBlock(STRATEGYBLOCK *sptr)
{
int a;
/* Reset name */
for(a = 0; a < SB_NAME_LENGTH; a++) {
sptr->SBname[a] = '\0';
}
FreeStBlockListPtr++;
*FreeStBlockListPtr = sptr;
NumFreeStBlocks++; /* One more free block */
}
STRATEGYBLOCK* CreateActiveStrategyBlock(void)
{
STRATEGYBLOCK *sb;
sb = AllocateStrategyBlock();
if(sb)
{
#if debug
GLOBALASSERT(sb->SBIsValid == 0);
sb->SBIsValid = 1;
#endif
*ActiveStBlockListPtr++ = sb;
NumActiveStBlocks++;
}
return sb;
}
int DestroyActiveStrategyBlock(STRATEGYBLOCK* sb)
{
int j = -1;
int i;
/* If the block ptr is OK, search the Active Blocks List */
if(sb)
{
for(i = 0; i < NumActiveStBlocks && j!=0; i++)
{
if(ActiveStBlockList[i] == sb)
{
ActiveStBlockList[i] = ActiveStBlockList[NumActiveStBlocks-1];
NumActiveStBlocks--;
ActiveStBlockListPtr--;
if(!sb->SBflags.preserve_until_end_of_level)
{
DeallocateStrategyBlock(sb); /* Back to Free List */
}
else
{
sb->SBflags.destroyed_but_preserved=1;
}
j = 0; /* Flag OK */
}
}
}
return(j);
}
STRATEGYBLOCK * AttachNewStratBlock
(
MODULE* moptr,
MODULEMAPBLOCK* momptr,
DISPLAYBLOCK* dptr
)
{
/*oh for a constructor*/
/* fails if any of the above has a
stratgey block attached*/
STRATEGYBLOCK* sptr;
int i;
GLOBALASSERT(momptr || dptr);
sptr = CreateActiveStrategyBlock();
if (sptr == 0) return 0;
InitialiseSBValues(sptr);
for(i = 0; i < SB_NAME_LENGTH; i++);
{
sptr->SBname[i] = '\0';
}
sptr->SBmomptr = momptr;
if(moptr)
{
/* GLOBALASSERT(!moptr->m_sbptr); HACK*/
moptr->m_sbptr = sptr;
sptr->SBmoptr = moptr;
}
if(dptr)
{
GLOBALASSERT(!dptr->ObStrategyBlock);
dptr->ObStrategyBlock = sptr;
sptr->SBdptr = dptr;
}
else
{
sptr->SBflags.no_displayblock = 1;
}
return(sptr);
}
void InitialiseSBValues(STRATEGYBLOCK* sptr)
{
sptr->I_SBtype = I_BehaviourNull;
sptr->SBdataptr = (void *)0x0;
sptr->SBDamageBlock.Health=0;
sptr->SBDamageBlock.Armour=0;
sptr->SBDamageBlock.SB_H_flags.AcidResistant=0;
sptr->SBDamageBlock.SB_H_flags.FireResistant=0;
sptr->SBDamageBlock.SB_H_flags.ElectricResistant=0;
sptr->SBDamageBlock.SB_H_flags.PerfectArmour=0;
sptr->SBDamageBlock.SB_H_flags.ElectricSensitive=0;
sptr->SBDamageBlock.SB_H_flags.Indestructable=0;
sptr->SBflags.please_destroy_me = 0;
sptr->SBflags.no_displayblock = 0;
sptr->SBflags.request_operate = 0;
sptr->SBflags.preserve_until_end_of_level = 0;
sptr->SBflags.destroyed_but_preserved = 0;
sptr->SBflags.not_on_motiontracker = 0;
sptr->integrity = 0;
sptr->maintainVisibility = 0; /* patrRWH - function to search thgough the list of active*/
sptr->containingModule = (MODULE *)0; /* patrstrat blocks and return the pointer*/
sptr->shapeIndex = 0; /* patr*/
sptr->SBmoptr = (MODULE*)0x0;
sptr->SBmomptr = (MODULEMAPBLOCK*)0x0;
sptr->SBmorphctrl = (MORPHCTRL*)0x0;
sptr->SBdptr=NULL;
sptr->name=0;
}
/*
RWH - function to search thgough the list of active
strat blocks and return the pointer
*/
STRATEGYBLOCK* FindSBWithName(char* id_name)
{
int stratblock = NumActiveStBlocks;
int i;
GLOBALASSERT(stratblock);
if(!id_name)
return NULL;
//If the name is all 0`s I want to return a null pointer - Richard.
for(i=0;i<SB_NAME_LENGTH;i++)
{
if(id_name[i]) break;
}
if(i==SB_NAME_LENGTH)
{
return NULL;
}
while(--stratblock >= 0)
{
STRATEGYBLOCK* sbptr = ActiveStBlockList[stratblock];
GLOBALASSERT(sbptr);
if(sbptr->SBname)
{
if(NAME_ISEQUAL(sbptr->SBname, id_name))
{
return((sbptr));
}
}
}
// we have to return null for lifts - so that
// we know that the lift is outside the env
return(NULL);
}
static STRATEGYBLOCK SB_Preserved[MAX_PRESERVED_SB];
static int Num_SB_Preserved;
void InitPreservedSBs()
{
Num_SB_Preserved = 0;
}
void PreserveStBlocksInModule(MODULE* containing_mod)
{
// this used within level - find objects in module
// all will have sbs
int i;
int max_x, min_x, max_y, min_y, max_z, min_z;
max_x = containing_mod->m_maxx + containing_mod->m_world.vx;
min_x = containing_mod->m_minx + containing_mod->m_world.vx;
max_y = containing_mod->m_maxy + containing_mod->m_world.vy;
min_y = containing_mod->m_miny + containing_mod->m_world.vy;
max_z = containing_mod->m_maxz + containing_mod->m_world.vz;
min_z = containing_mod->m_minz + containing_mod->m_world.vz;
GLOBALASSERT(Num_SB_Preserved == 0);
for(i = 0; i < NumActiveStBlocks && Num_SB_Preserved < MAX_PRESERVED_SB; i++)
{
VECTORCH obj_world;
STRATEGYBLOCK *sbptr;
DYNAMICSBLOCK *dynptr;
sbptr = ActiveStBlockList[i];
if(!(dynptr = sbptr->DynPtr))
continue;
obj_world = dynptr->Position;
if(obj_world.vx < max_x)
if(obj_world.vx > min_x)
if(obj_world.vz < max_z)
if(obj_world.vz > min_z)
if(obj_world.vy < max_y)
if(obj_world.vy > min_y)
{
// copy name into somthing
if(sbptr->I_SBtype == I_BehaviourMarinePlayer ||
sbptr->I_SBtype == I_BehaviourMarinePlayer ||
sbptr->I_SBtype == I_BehaviourMarinePlayer)
{
SB_Preserved[Num_SB_Preserved] = *sbptr;
Num_SB_Preserved++;
}
}
}
}
BOOL SBNeededForNextEnv(STRATEGYBLOCK* sbptr)
{
int i = 0;
if(Num_SB_Preserved == 0)
return(0);
if (sbptr->I_SBtype!=I_BehaviourMarinePlayer)
if (sbptr->I_SBtype!=I_BehaviourAlienPlayer)
if (sbptr->I_SBtype!=I_BehaviourPredatorPlayer)
if (NAME_ISNULL(sbptr->SBname))
return(0);
for(i = 0; i < Num_SB_Preserved; i++)
{
STRATEGYBLOCK *pres_sbptr;
pres_sbptr = &SB_Preserved[i];
if(NAME_ISEQUAL(pres_sbptr->SBname, sbptr->SBname))
return(1);
}
return(0);
}
void AddPreservedSBsToActiveList()
{
int i;
STRATEGYBLOCK *new_sbptr;
for(i = 0; i < Num_SB_Preserved; i++)
{
new_sbptr = CreateActiveStrategyBlock();
*new_sbptr = SB_Preserved[i];
if(new_sbptr->I_SBtype == I_BehaviourMarinePlayer ||
new_sbptr->I_SBtype == I_BehaviourMarinePlayer ||
new_sbptr->I_SBtype == I_BehaviourMarinePlayer)
{
DYNAMICSBLOCK *playerDynPtr;
Player->ObStrategyBlock = new_sbptr;
playerDynPtr = Player->ObStrategyBlock->DynPtr;
// Need to copy some of the preserved SB info into the appropriate places
Player->ObWorld = playerDynPtr->Position;
Player->ObMat = playerDynPtr->OrientMat;
Player->ObEuler = playerDynPtr->OrientEuler;
playerDynPtr->PrevPosition = playerDynPtr->Position;
playerDynPtr->PrevOrientMat = playerDynPtr->OrientMat;
playerDynPtr->PrevOrientEuler = playerDynPtr->OrientEuler;
playerDynPtr->LinVelocity.vx = 0;
playerDynPtr->LinVelocity.vy = 0;
playerDynPtr->LinVelocity.vz = 0;
playerDynPtr->LinImpulse.vx = 0;
playerDynPtr->LinImpulse.vy = 0;
playerDynPtr->LinImpulse.vz = 0;
playerDynPtr->AngVelocity.EulerX = 0;
playerDynPtr->AngVelocity.EulerY = 0;
playerDynPtr->AngVelocity.EulerZ = 0;
playerDynPtr->AngImpulse.EulerX = 0;
playerDynPtr->AngImpulse.EulerY = 0;
playerDynPtr->AngImpulse.EulerZ = 0;
}
// we will almost certainly need
// some clean up here. esp for the
// LIFT_FLOOR_SWITCHES and for objects
// whose shape reference has changed
}
}
void TeleportPreservedSBsToNewEnvModule(MODULE *new_pos, MODULE* old_pos, int orient_change)
{
int i;
VECTORCH mod_offset;
mod_offset.vx = new_pos->m_world.vx - old_pos->m_world.vx;
mod_offset.vy = new_pos->m_world.vy - old_pos->m_world.vy;
mod_offset.vz = new_pos->m_world.vz - old_pos->m_world.vz;
for(i = 0; i < Num_SB_Preserved; i++)
{
VECTORCH obj_world;
VECTORCH pos_rel;
STRATEGYBLOCK *sbptr;
DYNAMICSBLOCK *dynptr;
sbptr = &SB_Preserved[i];
dynptr = sbptr->DynPtr;
GLOBALASSERT(dynptr);
obj_world = sbptr->DynPtr->Position;
{
// okay we need to find our relative position to the moduke
int cos;
int sin;
int angle;
MATRIXCH mat;
pos_rel.vx = dynptr->Position.vx - old_pos->m_world.vx;
pos_rel.vy = dynptr->Position.vy - old_pos->m_world.vy;
pos_rel.vz = dynptr->Position.vz - old_pos->m_world.vz;
if(orient_change == 1 || orient_change == -3)
angle = 1024;
else if(orient_change == 2 || orient_change == -2)
angle = 2048;
else if(orient_change == 3 || orient_change == -1)
angle = 3072;
else
angle = 0;
cos = GetCos(angle);
sin = GetSin(angle);
mat.mat11 = cos;
mat.mat12 = 0;
mat.mat13 = -sin;
mat.mat21 = 0;
mat.mat22 = 65536;
mat.mat23 = 0;
mat.mat31 = sin;
mat.mat32 = 0;
mat.mat33 = cos;
// rotate the relative object about the center of the
// module and rotate the abject about its own y-axis
RotateVector(&pos_rel, &mat);
MatrixMultiply(&dynptr->OrientMat,&mat,&dynptr->OrientMat);
MatrixToEuler(&dynptr->OrientMat, &dynptr->OrientEuler);
}
#if 0
dynptr->Position.vx = mod_offset.vx;
dynptr->Position.vy = mod_offset.vy;
dynptr->Position.vz = mod_offset.vz;
dynptr->PrevPosition.vx = mod_offset.vx;
dynptr->PrevPosition.vy = mod_offset.vy;
dynptr->PrevPosition.vz = mod_offset.vz;
#endif
dynptr->Position.vx = pos_rel.vx + new_pos->m_world.vx;
dynptr->Position.vy = pos_rel.vy + new_pos->m_world.vy;
dynptr->Position.vz = pos_rel.vz + new_pos->m_world.vz;
dynptr->PrevPosition.vx = -pos_rel.vx + old_pos->m_world.vx;
dynptr->PrevPosition.vy = -pos_rel.vy + old_pos->m_world.vy;
dynptr->PrevPosition.vz = -pos_rel.vz + old_pos->m_world.vz;
}
}
// RWH 5/6/97 these next two functions were 1, changed and 2, added
// to deal with deallocating stblocks at the end of behaviours
// this stops problems with accessing defunct strategy blocks
// via collision reports
void DestroyAnyStrategyBlock(STRATEGYBLOCK *sbptr)
{
GLOBALASSERT(sbptr);
sbptr->SBflags.please_destroy_me = 1;
}
void RemoveDestroyedStrategyBlocks(void)
{
/*
Go backwards through the strategy block.
This should prevent any strategy blocks from being skipped when they
get shuffled down from the end of the array.
*/
int i = NumActiveStBlocks;
while(i)
{
STRATEGYBLOCK* sbptr = ActiveStBlockList[--i];
if(sbptr->SBflags.please_destroy_me)
{
RemoveBehaviourStrategy(sbptr);
} else {
/* Also... gibb aliens? */
if (sbptr->I_SBtype==I_BehaviourAlien) {
ALIEN_STATUS_BLOCK *alienStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
alienStatusPointer=(ALIEN_STATUS_BLOCK *)(sbptr->SBdataptr);
if (alienStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,alienStatusPointer->HModelController.section_data,alienStatusPointer->GibbFactor);
alienStatusPointer->GibbFactor=0;
} else if (alienStatusPointer->GibbFactor<0) {
KillRandomSections(alienStatusPointer->HModelController.section_data,alienStatusPointer->GibbFactor);
alienStatusPointer->GibbFactor=0;
}
} else if (
(sbptr->I_SBtype==I_BehaviourMarine)
|| (sbptr->I_SBtype==I_BehaviourSeal)
) {
MARINE_STATUS_BLOCK *marineStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbptr->SBdataptr);
if (marineStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,marineStatusPointer->HModelController.section_data,marineStatusPointer->GibbFactor);
marineStatusPointer->GibbFactor=0;
} else if (marineStatusPointer->GibbFactor<0) {
KillRandomSections(marineStatusPointer->HModelController.section_data,-(marineStatusPointer->GibbFactor));
marineStatusPointer->GibbFactor=0;
}
} else if (sbptr->I_SBtype==I_BehaviourPredator) {
PREDATOR_STATUS_BLOCK *predatorStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
predatorStatusPointer=(PREDATOR_STATUS_BLOCK *)(sbptr->SBdataptr);
if (predatorStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,predatorStatusPointer->HModelController.section_data,predatorStatusPointer->GibbFactor);
predatorStatusPointer->GibbFactor=0;
} else if (predatorStatusPointer->GibbFactor<0) {
KillRandomSections(predatorStatusPointer->HModelController.section_data,-(predatorStatusPointer->GibbFactor));
predatorStatusPointer->GibbFactor=0;
}
} else if (sbptr->I_SBtype==I_BehaviourXenoborg) {
XENO_STATUS_BLOCK *xenoStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
xenoStatusPointer=(XENO_STATUS_BLOCK *)(sbptr->SBdataptr);
if (xenoStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,xenoStatusPointer->HModelController.section_data,xenoStatusPointer->GibbFactor);
xenoStatusPointer->GibbFactor=0;
} else if (xenoStatusPointer->GibbFactor<0) {
KillRandomSections(xenoStatusPointer->HModelController.section_data,-(xenoStatusPointer->GibbFactor));
xenoStatusPointer->GibbFactor=0;
}
} else if (sbptr->I_SBtype==I_BehaviourNetCorpse) {
NETCORPSEDATABLOCK *corpseStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
corpseStatusPointer=(NETCORPSEDATABLOCK *)(sbptr->SBdataptr);
if(corpseStatusPointer->GibbFactor)
{
/*get a seed for the RNG so that we can send gibbing to other
network players*/
int seed=FastRandom();
SetSeededFastRandom(seed);
if(AvP.Network != I_No_Network)
{
AddNetMsg_Gibbing(sbptr,corpseStatusPointer->GibbFactor,seed);
}
if (corpseStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,corpseStatusPointer->HModelController.section_data,corpseStatusPointer->GibbFactor);
corpseStatusPointer->GibbFactor=0;
} else if (corpseStatusPointer->GibbFactor<0) {
KillRandomSections(corpseStatusPointer->HModelController.section_data,-(corpseStatusPointer->GibbFactor));
corpseStatusPointer->GibbFactor=0;
}
}
} else if (sbptr->I_SBtype==I_BehaviourHierarchicalFragment) {
HDEBRIS_BEHAV_BLOCK *debrisStatusPointer;
LOCALASSERT(sbptr);
LOCALASSERT(sbptr->DynPtr);
debrisStatusPointer=(HDEBRIS_BEHAV_BLOCK *)(sbptr->SBdataptr);
if (debrisStatusPointer->GibbFactor>0) {
Extreme_Gibbing(sbptr,debrisStatusPointer->HModelController.section_data,debrisStatusPointer->GibbFactor);
debrisStatusPointer->GibbFactor=0;
} else if (debrisStatusPointer->GibbFactor<0) {
KillRandomSections(debrisStatusPointer->HModelController.section_data,-(debrisStatusPointer->GibbFactor));
debrisStatusPointer->GibbFactor=0;
}
}
}
}
}
void DestroyAllStrategyBlocks(void)
{
int i = 0;
int a = NumActiveStBlocks;
while(i < a)
{
RemoveBehaviourStrategy(ActiveStBlockList[i++]);
}
//get rid of all the strategyblocks that have been preserved until the end of the level
for(i=0;i<maxstblocks;i++)
{
if(FreeStBlockData[i].SBflags.destroyed_but_preserved)
{
FreeStBlockData[i].SBflags.destroyed_but_preserved=0;
FreeStBlockData[i].SBflags.preserve_until_end_of_level=0;
DeallocateStrategyBlock(&FreeStBlockData[i]);
}
}
}
void AssignNewSBName(STRATEGYBLOCK *sbPtr) {
IncrementalSBname++;
if(IncrementalSBname>0xffffff)
{
IncrementalSBname=1;
}
*((int *)&sbPtr->SBname[4])=IncrementalSBname;
if(AvP.Network != I_No_Network)
{
//modify name to ensure uniqueness between players
extern DPID AVPDPNetID;
sbPtr->SBname[SB_NAME_LENGTH-1]=+10+PlayerIdInPlayerList(AVPDPNetID); /* Just to make sure... */
}
else
{
sbPtr->SBname[SB_NAME_LENGTH-1]=1; /* Just to make sure... */
}
}
void GivePlayerCloakAway(void) {
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
playerStatusPtr->cloakPositionGivenAway = 1;
playerStatusPtr->cloakPositionGivenAwayTimer = PLAYERCLOAK_POSTIONGIVENAWAYTIME;
}