Initial revision

This commit is contained in:
Steven Fuller 2001-07-01 00:55:22 +00:00 committed by Patryk Obara
parent 218ca90543
commit 2186d5f3f9
572 changed files with 2 additions and 29666 deletions

914
src/afont.c Normal file
View file

@ -0,0 +1,914 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "gamedef.h"
#include "font.h"
#include "indexfnt.hpp"
#define UseLocalAssert 1
#include "ourasert.h"
/* Roxbys font stuff. any comments will be useful!!!
font control - Fonts description and sturctures game/plat/font.h
Platform dependent processing game/plat/platsup.c or ddplat.cpp
*/
/* general ideas. Crap I know!!!
written to maintain compatiblity with the current texture (bitmap) processing tools.
all the information about spacing of the font is maintained witin the bitmap itself,
using hotspots for the texture processing, that way we dont need extra tools to convert
fonts. It also allows complete font positioning (except different letter combos changing)
I have shifted most of the emphasis onto the artists to set up the font and to mark it how they
see fit. All the fonts must contain hotspots for all the letters. In that way we can easily
expand fonts. The character offests at the mo are simply -32. We may have to set up jump tables
at some later date to get chars for different languages.
Nothing supports anti-aliasing at the moment. Be careful with colours!!!
Most of the info is being passed as locals. Clumsy I know. I didnt want to take up more
space than was nessecery
HARD coded. Names of the fonts
Number of fonts to load
Number of characters in the font. you can leave letters blank. The number of
characters in the fonts can be changed for different languages
AVP-Win95
This loads all the fonts in the structure PFFONT AvpFonts[] that is passed
to while NUM_FONTS. The Imageheader->ImagePtr for the data is maintained
untill we have processd the characters. I dont fancy manipulating the data
in a LPDIRECTDRAWSURFACE. The character descriptors in the font contain
nothing but a src RECT. the void* pointer in the PFFONT structure in this
case is cast to LPDIRECTDRAWSURFACE.
Not that the entire font is placed into a
file That is then processed. CLUT where to
put the CLU???? Put it into the vid memory.
use a void*
*/
/*
Only have 8 bit support a tne moment. More to come!!!
Screen modes. I recommend loading up different fonts for different screen modes.
Simply reference a different structure.
*/
#define CHAR_WIDTH(font_num, offset) ((AvpFonts[font_num].srcRect[offset].right - AvpFonts[font_num].srcRect[offset].left))
#define CHAR_HEIGHT(font_num, offset) ((AvpFonts[font_num].srcRect[offset].bottom - AvpFonts[font_num].srcRect[offset].top))
#define IS_CHAR_WHITE_SPACE(ch) ((ch == '\t' || ch == '\n' || ch == ' ' || (int)ch == 0x0))
static int ProcessFontEntry
(
PFFONT* font,
unsigned char* fontstartaddress,
unsigned pitch,
int* countfromrow,
int* countfromcol,
int charnum
);
static int ProcessLineLength
(
char* start_ch, // start char of string
AVP_FONTS fontnum, // the font we are using
int offset, // the offset from the font
int max_width, // the width of the line
char** end_ch, // filled with end address
int* line_length
);
void LoadAllFonts()
{
// these fonts end up being in memory all the time,
// I will also supply a function which is delete
// specific font.
int fontnum = 0;
while(fontnum < NUM_FONTS)
{
/* load the font in turn */
LoadPFFont(fontnum);
fontnum ++;
}
}
void LoadPFFont(int fontnum)
{
// these fonts end up being in memory all the time,
// I will also supply a function which is delete
// specific font.
PFFONT *font = &AvpFonts[fontnum];
unsigned nPitch;
unsigned char * pSurface;
LoadFont(font);
/* get the hotspot color first entry in */
if(font->fttexBitDepth == 15)font->fttexBitDepth = 16;
pSurface = FontLock(font,&nPitch);
GLOBALASSERT(pSurface);
font->hotSpotValue = *(unsigned *)pSurface & (font->fttexBitDepth<32 ? (1<<font->fttexBitDepth)-1 : 0xffffffffU);
/* the hotspot value is the top-left pixel */
{
int charnum = 0;
int countfromrow = 1;
int countfromcol = 0;
/*
find the hotspots and send everything to the
processing function. This part of routine find the
hotspots in numbers of pixels
*/
/*Top line of the texture is redundent we get the hotspot from this*/
/*edge of the texture has only lines*/
while(charnum < font->num_chars_in_font)
{
ProcessFontEntry(font,pSurface,nPitch,&countfromrow,&countfromcol,charnum);
charnum++;
}
#if 0
// Taken out by DHM 26/11/97:
fontnum++;
#endif
charnum = 0;
}
FontUnlock(font);
#if SupportWindows95
INDEXFNT_PFLoadHook
(
(FontIndex) fontnum,
// FontIndex I_Font_New,
font // PFFONT *pffont_New
);
#endif
}
static int ProcessFontEntry
(
PFFONT* font,
unsigned char* fontstartaddress,
unsigned pitch,
int* countfromrow,
int* countfromcol,
int charnum
)
{
/*
okay set the starting point
countfromrow marks the current depth of the processing row in the texture.
countfromcol marks how far along the current coloum we have processed
* = HOTSPOT .. the first pixel is used as the hotspot
**********************
* ** ** **** * <---- startfromrow
###
#
## # # ###
# # # # # ##
### ### #### ##
* * # * **** * Blank chars marked by two hotspots adjacent
### ^^ |at the top and the bottom
* * || |
^ ||______|
|
|
startfromcol
********************* Note that the spot in col 0 marks a new linw of chars
*/
int curr_row = *countfromrow;
int curr_col = *countfromcol;
int y_offset = 0, x_offset = curr_col;
GLOBALASSERT(font);
GLOBALASSERT(fontstartaddress);
GLOBALASSERT(charnum < font->num_chars_in_font);
GLOBALASSERT(curr_row < font->fttexHeight);
GLOBALASSERT(curr_col <= font->fttexWidth);
/*remember that all the corrdinates are done by pixels
find the x and y corrdinates of the left lower hotspot
we process each line (row) from startfromrow to the end
first find the next marker in startfromrow
*/
// only supported if bit depth is a whole number of bytes
GLOBALASSERT(8==font->fttexBitDepth || 16==font->fttexBitDepth || 24==font->fttexBitDepth || 32==font->fttexBitDepth);
while(1)
{
// this bit processes the chars, finds uvs, extents and fills in the sturcture*/
// count along the row to find the next x position
unsigned int colour_here;
if(x_offset > font->fttexWidth - 1)
{
// reached the end of the line! reset x and then y
x_offset = 0;
curr_col = 0;
curr_row += font->fontHeight; // max line height
*countfromrow = curr_row;
GLOBALASSERT(curr_row < font->fttexHeight);
}
switch (font->fttexBitDepth)
{
default:
GLOBALASSERT(0);
case 8:
colour_here = *(fontstartaddress + (curr_row*pitch + x_offset));
break;
case 16:
colour_here = *(unsigned short *)(fontstartaddress + (curr_row*pitch + 2*x_offset));
break;
case 24:
{
unsigned char * pPixel = fontstartaddress + (curr_row*pitch + 3*x_offset);
// assuming the right endianness
colour_here = pPixel[0] | (unsigned)pPixel[1] << 8 | (unsigned)pPixel[2] << 16;
break;
}
case 32:
colour_here = *(unsigned *)(fontstartaddress + (curr_row*pitch + 4*x_offset));
break;
}
if(colour_here == font->hotSpotValue)
{
int width = -1, height = -1;
/* set up the uv corrds of the top left corner*/
int u = x_offset + 1;
int v = curr_row + 1;
/* scan down to give height*/
for(y_offset = (curr_row + 1); y_offset < font->fttexHeight; y_offset++)
{
switch (font->fttexBitDepth)
{
default:
GLOBALASSERT(0);
case 8:
colour_here = *(fontstartaddress + (y_offset*pitch + x_offset));
break;
case 16:
colour_here = *(unsigned short *)(fontstartaddress + (y_offset*pitch + 2*x_offset));
break;
case 24:
{
unsigned char * pPixel = fontstartaddress + (y_offset*pitch + 3*x_offset);
// assuming the right endianness
colour_here = pPixel[0] | (unsigned)pPixel[1] << 8 | (unsigned)pPixel[2] << 16;
break;
}
case 32:
colour_here = *(unsigned *)(fontstartaddress + (y_offset*pitch + 4*x_offset));
break;
}
if(colour_here == font->hotSpotValue)
{
height = y_offset - curr_row - 1; // -1 because we exclude the top and bottom hotspots
break;
}
}
/* scan along to get the width*/
for(++x_offset; x_offset < font->fttexWidth; x_offset ++)
{
switch (font->fttexBitDepth)
{
default:
GLOBALASSERT(0);
case 8:
colour_here = *(fontstartaddress + (curr_row*pitch + x_offset));
break;
case 16:
colour_here = *(unsigned short *)(fontstartaddress + (curr_row*pitch + 2*x_offset));
break;
case 24:
{
unsigned char * pPixel = fontstartaddress + (curr_row*pitch + 3*x_offset);
// assuming the right endianness
colour_here = pPixel[0] | (unsigned)pPixel[1] << 8 | (unsigned)pPixel[2] << 16;
break;
}
case 32:
colour_here = *(unsigned *)(fontstartaddress + (curr_row*pitch + 4*x_offset));
break;
}
if(colour_here == font->hotSpotValue)
{
width = x_offset - curr_col - 1; // exclude end hotspot
break;
}
}
*countfromcol = x_offset + 1; /* ready for the next char*/
/*fill in the data structure - platform dependent*/
FillCharacterSlot(u, v, width, height, charnum, font);
return 0;
}
x_offset++;
}
return 0;
}
#if 0 // obsolete
static int Process8BitEntry(PFFONT* font,
char* fontstartaddress,
int* countfromrow,
int* countfromcol,
int charnum)
{
/*
okay set the starting point
countfromrow marks the current depth of the processing row in the texture.
countfromcol marks how far along the current coloum we have processed
* = HOTSPOT .. the first pixel is used as the hotspot
**********************
* ** ** **** * <---- startfromrow
###
#
## # # ###
# # # # # ##
### ### #### ##
* * # * **** * Blank chars marked by two hotspots adjacent
### ^^ |at the top and the bottom
* * || |
^ ||______|
|
|
startfromcol
********************* Note that the spot in col 0 marks a new linw of chars
*/
int curr_row = *countfromrow;
int curr_col = *countfromcol;
int y_offset = 0, x_offset = curr_col;
GLOBALASSERT(font);
GLOBALASSERT(fontstartaddress);
GLOBALASSERT(charnum < font->num_chars_in_font);
GLOBALASSERT(curr_row < font->fttexHeight);
GLOBALASSERT(curr_col <= font->fttexWidth);
/*remember that all the corrdinates are done by pixels
find the x and y corrdinates of the left lower hotspot
we process each line (row) from startfromrow to the end
first find the next marker in startfromrow
*/
while(1)
{
// this bit processes the chars, finds uvs, extents and fills in the sturcture*/
// count along the row to find the next x position
unsigned int colour_here;
if(x_offset > font->fttexWidth - 1)
{
// reached the end of the line! reset x and then y
x_offset = 0;
curr_col = 0;
curr_row += font->fontHeight; // max line height
*countfromrow = curr_row;
GLOBALASSERT(curr_row < font->fttexHeight);
}
colour_here = (int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset));
if(colour_here == font->hotSpotValue)
{
int width = -1, height = -1;
/* set up the uv corrds of the top left corner*/
int u = x_offset + 1;
int v = curr_row + 1;
/* scan down to give height*/
for(y_offset = (curr_row + 1); y_offset < font->fttexHeight; y_offset++)
{
colour_here = (int)*(fontstartaddress + (y_offset*font->fttexWidth + x_offset));
if(colour_here == font->hotSpotValue)
{
height = y_offset - curr_row - 1; // -1 because we exclude the top and bottom hotspots
break;
}
}
/* scan along to get the width*/
for(++x_offset; x_offset < font->fttexWidth; x_offset ++)
{
colour_here = (int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset));
if(colour_here == font->hotSpotValue)
{
width = x_offset - curr_col - 1; // exclude end hotspot
break;
}
}
*countfromcol = x_offset + 1; /* ready for the next char*/
/*fill in the data structure - platform dependent*/
FillCharacterSlot(u, v, width, height, charnum, font);
return 0;
}
x_offset++;
} a
}
static int Process16BitEntry(PFFONT *font,
char* fontstartaddress,
int* countfromrow,
int* countfromcol,
int charnum)
{
int curr_row = *countfromrow;
int curr_col = *countfromcol;
int y_offset = 0, x_offset = curr_col;
GLOBALASSERT(font);
GLOBALASSERT(fontstartaddress);
GLOBALASSERT(charnum < font->num_chars_in_font);
GLOBALASSERT(curr_row < font->fttexHeight);
GLOBALASSERT(curr_col <= font->fttexWidth);
/*remember that all the corrdinates are done by pixels
find the x and y corrdinates of the left lower hotspot
we process each line (row) from startfromrow to the end
first find the next marker in startfromrow
*/
while(1)
{
// this bit processes the chars, finds uvs, extents and fills in the sturcture*/
// count along the row to find the next x position
unsigned int colour_here;
if(x_offset > font->fttexWidth - 1)
{
// reached the end of the line! reset x and then y
x_offset = 0;
curr_col = 0;
curr_row += font->fontHeight; // max line height
*countfromrow = curr_row;
GLOBALASSERT(curr_row < font->fttexHeight);
}
{
unsigned int colour_high = 0x000000ff & (unsigned int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset)*2);
unsigned int colour_low = 0x000000ff & (int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset)*2 + 1);
colour_here = (colour_high << 8) | colour_low;
}
if(colour_here == font->hotSpotValue)
{
int width = -1, height = -1;
/* set up the uv corrds of the top left corner*/
int u = x_offset + 1;
int v = curr_row + 1;
/* scan down to give height*/
for(y_offset = (curr_row + 1); y_offset < font->fttexHeight; y_offset++)
{
{
int colour_high = 0x000000ff & (int)*(fontstartaddress + (y_offset*font->fttexWidth + x_offset)*2);
int colour_low = 0x000000ff & (int)*(fontstartaddress + (y_offset*font->fttexWidth + x_offset)*2 + 1);
colour_here = (colour_high << 8) | colour_low;
}
if(colour_here == font->hotSpotValue)
{
height = y_offset - curr_row - 1; // -1 because we exclude the top and bottom hotspots
break;
}
}
/* scan along to get the width*/
for(++x_offset; x_offset < font->fttexWidth; x_offset ++)
{
{
int colour_high = 0x000000ff & (int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset)*2);
int colour_low = 0x000000ff & (int)*(fontstartaddress + (curr_row*font->fttexWidth + x_offset)*2 + 1);
colour_here = (colour_high << 8) | colour_low;
}
if(colour_here == font->hotSpotValue)
{
width = x_offset - curr_col - 1; // exclude end hotspot
break;
}
}
*countfromcol = x_offset + 1; /* ready for the next char*/
/*fill in the data structure - platform dependent*/
FillCharacterSlot(u, v, width, height, charnum, font);
return 0;
}
x_offset++;
}
return 0;
}
static int Process24BitEntry(PFFONT* font,
char* fontstartaddress,
int* countfromrow,
int* countfromcol,
int charnum)
{
return 0;
}
#endif
void BLTWholeFont(int fontnum, int x , int y, int win_width)
{
int i = 0;
int plotto_x = x, plotto_y = y;
while(i < AvpFonts[fontnum].num_chars_in_font)
{
int charwidth = AvpFonts[fontnum].srcRect[i].right - AvpFonts[fontnum].srcRect[i].left;
if((charwidth + plotto_x - x) > win_width)
{
plotto_y += AvpFonts[fontnum].fontHeight;
plotto_x= x;
}
BLTFontOffsetToHUD(&AvpFonts[fontnum], plotto_x, plotto_y, i);
plotto_x += charwidth + 1;
i++;
}
return;
}
void BLTString(FONT_DESC str_packet)
{
PFFONT font = AvpFonts[str_packet.fontnum];
unsigned char *strptr = str_packet.string;
int offset = 0;
int not_finished = Yes;
int pos_x = str_packet.destx;
int pos_y = str_packet.desty;
int white_space_width = CHAR_WIDTH(str_packet.fontnum, 0);
// set up the font processing varibles depending on the type of font
switch(font.font_type)
{
case(I_FONT_NUMERIC):
{
offset = 0x30;
break;
}
case(I_FONT_UC_NUMERIC):
{
offset = 0x20;
break;
}
case(I_FONT_UCLC_NUMERIC):
{
offset = 0x20;
break;
}
default:
GLOBALASSERT(2<1);
}
while(not_finished)
{
int line_length;
char *end_char;
// find the line length and the end char in the line
not_finished = ProcessLineLength
(
strptr, // start char of string
str_packet.fontnum, // the font we are using
offset, // the offset from the font
str_packet.width, // the width of the line
&end_char, // filled with end address
&line_length // filled with line length
);
// work out where to print the line
if(line_length)
{
switch(str_packet.just)
{
case FJ_LEFT_JUST:
{
pos_x = str_packet.destx;
break;
}
case FJ_CENTRED:
{
pos_x = str_packet.destx + ((str_packet.width - line_length) >> 1);
break;
}
case FJ_RIGHT_JUST:
{
pos_x = str_packet.destx + (str_packet.width - line_length);
break;
}
default:
{
;
}
}
// now print the line untill we reach the address of
// the end char
do
{
if(*strptr == ' ')
{
pos_x += white_space_width;
}
else if(*strptr == '\t')
{
pos_x += 4*white_space_width;
}
else if(*strptr == '\n' || strptr == 0x0)
{
GLOBALASSERT(strptr == end_char);
}
else if((int)*strptr == 0xD)
{
// carrige return
// do nothing - our next char should be '\n'
GLOBALASSERT(*(strptr + 1) == '\n');
}
else
{
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
int end_pos = pos_x + CHAR_WIDTH(str_packet.fontnum, ((int)*strptr - offset));
int bottom_pos = pos_y + CHAR_HEIGHT(str_packet.fontnum, ((int)*strptr - offset));
if(end_pos > ScreenDescriptorBlock.SDB_Width || pos_x < 0)
{
//dont draw
//not_finished = No;
}
else if( bottom_pos > ScreenDescriptorBlock.SDB_Height || pos_y < 0)
{
not_finished = No;
}
else
{
pos_x += BLTFontOffsetToHUD
(
&font,
pos_x,
pos_y,
(int)*strptr - offset
);
pos_x ++; // to make space between letters
}
}
}
while(++strptr != end_char);
pos_y += font.fontHeight - 2;
}
strptr++;
}
}
/*
RWH - changes to font line processing
This function takes a pointer to a string a font and a width and
puts the length of the line into line_length AND puts the end char address into end_ch
It returns 0 when we have reached the end of a string
*/
int ProcessLineLength
(
char* start_ch, // start char of string
AVP_FONTS fontnum, // the font we are using
int offset, // the offset from the font
int max_width, // the width of the line
char** end_ch, // filled with end address
int* line_length
)
{
int continue_to_process_word = Yes;
int white_space_width = CHAR_WIDTH(fontnum, 0);
char *word_ptr = start_ch;
*line_length = 0;
if(start_ch == NULL)
{
*end_ch = NULL;
*line_length = 0;
return 0;
}
// first process any white space at the end of the
// line out
while(*start_ch == ' ')
{
// make sure we havent run out
// of chars to process
if(*start_ch == 0x0)
{
*end_ch = NULL;
*line_length = 0;
return 0;
}
start_ch++;
}
// Now we can start on the characters in the line
// note that we have to have two loops. The first
// continues untill we break out of it. The second
// adds up the length of each word and sees if the line
// with the new word will overrun the max_width
// the word_ptr points to the current char - it is only incremented
// when we can be sure that we can add the current letter to the word
while(1)
{
int word_length = 0;
continue_to_process_word = Yes;
while(continue_to_process_word)
{
// is the next char white space ?
// if so close the word
if(IS_CHAR_WHITE_SPACE(*(word_ptr + 1)))
{
// hit white space - finish this current word but only
// AFTER we have processed the current char
continue_to_process_word = No;
}
// need to process every white space seperately
if(*word_ptr == '\t')
{
// a one char word!
word_length = 4 * white_space_width;
continue_to_process_word = No;
word_ptr++;
}
else if(*word_ptr == 0x0)
{
// reached end of file - need to return 0
*end_ch = word_ptr;
return 0;
}
else if(*word_ptr == '\n')
{
*end_ch = word_ptr;
return 1;
}
else if(*word_ptr == ' ')
{
if(word_length)
{
// tag on the white space onto the word length
word_length += white_space_width;
}
// other wise keep on tiking on
word_ptr++;
}
else
{
// yeah add a letter to the word length
int char_off = (char)(*word_ptr - offset);
word_length += CHAR_WIDTH(fontnum, char_off);
word_length ++; //for space between lettes
word_ptr++; //process next char
}
}
// okay we have the length of this word - check to see if
// it overruns the end of the line - if it is too long,
// break out of the line loop
if((word_length + *line_length) >= max_width)
{
*end_ch = start_ch;
return 1;
}
else
{
*line_length += word_length;
// set up the next word save the beginning of teh word in start_ch
start_ch = word_ptr;
}
}
}

198
src/avp/ai_sight.c Normal file
View file

@ -0,0 +1,198 @@
/*KJL*****************************************
* AI_Sight.c handles the NPC's visual senses *
*****************************************KJL*/
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "dynblock.h"
#include "dynamics.h"
#include "los.h"
#include "ShowCmds.h"
#include "equipmnt.h"
#include "bh_marin.h"
#include "bh_xeno.h"
#include "targeting.h"
#include "bh_weap.h"
#include "AI_Sight.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern int MarineSight_FrustrumReject(STRATEGYBLOCK *sbPtr,VECTORCH *localOffset,STRATEGYBLOCK *target);
extern int FrisbeeSight_FrustrumReject(STRATEGYBLOCK *sbPtr,VECTORCH *localOffset,STRATEGYBLOCK *target);
int NPCCanSeeTarget(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target, int viewRange)
{
int frustrum_test;
/* connect eyeposition to head */
VECTORCH eyePosition = {0,-1500,0};
LOCALASSERT(target);
LOCALASSERT(sbPtr);
if (target->containingModule==NULL) {
return(0);
}
if (sbPtr->containingModule==NULL) {
return(0);
}
if ((target->SBdptr==NULL)||(sbPtr->SBdptr==NULL)) {
if ((IsModuleVisibleFromModule(target->containingModule,sbPtr->containingModule))) {
return(1);
} else {
return(0);
}
} else {
switch (sbPtr->I_SBtype) {
case I_BehaviourFrisbee:
{
MATRIXCH WtoL;
VECTORCH offset, sourcepos, targetpos;
FRISBEE_BEHAV_BLOCK *frisbeeStatusPointer;
SECTION_DATA *disc_sec;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->containingModule);
frisbeeStatusPointer = (FRISBEE_BEHAV_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(frisbeeStatusPointer);
/* Arc reject. */
disc_sec=GetThisSectionData(frisbeeStatusPointer->HModelController.section_data,"Mdisk");
if (disc_sec) {
WtoL=disc_sec->SecMat;
sourcepos=disc_sec->World_Offset;
} else {
WtoL=sbPtr->DynPtr->OrientMat;
GetTargetingPointOfObject_Far(sbPtr,&sourcepos);
}
GetTargetingPointOfObject_Far(target,&targetpos);
offset.vx=sourcepos.vx-targetpos.vx;
offset.vy=sourcepos.vy-targetpos.vy;
offset.vz=sourcepos.vz-targetpos.vz;
TransposeMatrixCH(&WtoL);
RotateVector(&offset,&WtoL);
frustrum_test=FrisbeeSight_FrustrumReject(sbPtr,&offset,target);
}
break;
case I_BehaviourMarine:
case I_BehaviourSeal:
{
MATRIXCH WtoL;
VECTORCH offset, sourcepos, targetpos;
MARINE_STATUS_BLOCK *marineStatusPointer;
SECTION_DATA *head_sec;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->containingModule);
marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(marineStatusPointer);
/* Arc reject. */
head_sec=GetThisSectionData(marineStatusPointer->HModelController.section_data,"head");
if (head_sec) {
WtoL=head_sec->SecMat;
sourcepos=head_sec->World_Offset;
} else {
WtoL=sbPtr->DynPtr->OrientMat;
GetTargetingPointOfObject_Far(sbPtr,&sourcepos);
}
GetTargetingPointOfObject_Far(target,&targetpos);
offset.vx=sourcepos.vx-targetpos.vx;
offset.vy=sourcepos.vy-targetpos.vy;
offset.vz=sourcepos.vz-targetpos.vz;
TransposeMatrixCH(&WtoL);
RotateVector(&offset,&WtoL);
frustrum_test=MarineSight_FrustrumReject(sbPtr,&offset,target);
}
break;
case I_BehaviourXenoborg:
{
MATRIXCH WtoL;
VECTORCH offset, sourcepos, targetpos;
XENO_STATUS_BLOCK *xenoStatusPointer;
SECTION_DATA *head_sec;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->containingModule);
xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(xenoStatusPointer);
/* Arc reject. */
head_sec=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"head");
if (head_sec) {
WtoL=head_sec->SecMat;
sourcepos=head_sec->World_Offset;
} else {
WtoL=sbPtr->DynPtr->OrientMat;
GetTargetingPointOfObject_Far(sbPtr,&sourcepos);
}
GetTargetingPointOfObject_Far(target,&targetpos);
offset.vx=sourcepos.vx-targetpos.vx;
offset.vy=sourcepos.vy-targetpos.vy;
offset.vz=sourcepos.vz-targetpos.vz;
TransposeMatrixCH(&WtoL);
RotateVector(&offset,&WtoL);
frustrum_test=XenoSight_FrustrumReject(sbPtr,&offset);
}
break;
case I_BehaviourAutoGun:
{
/* Less pretentious, based on the SB. */
MATRIXCH WtoL;
VECTORCH offset, sourcepos, targetpos;
/* Arc reject. */
WtoL=sbPtr->DynPtr->OrientMat;
GetTargetingPointOfObject_Far(sbPtr,&sourcepos);
GetTargetingPointOfObject_Far(target,&targetpos);
offset.vx=sourcepos.vx-targetpos.vx;
offset.vy=sourcepos.vy-targetpos.vy;
offset.vz=sourcepos.vz-targetpos.vz;
TransposeMatrixCH(&WtoL);
RotateVector(&offset,&WtoL);
frustrum_test=AGunSight_FrustrumReject(&offset);
}
break;
default:
frustrum_test=1;
break;
}
if (frustrum_test) {
RotateVector(&eyePosition,&(sbPtr->DynPtr->OrientMat));
eyePosition.vx += sbPtr->DynPtr->Position.vx;
eyePosition.vy += sbPtr->DynPtr->Position.vy;
eyePosition.vz += sbPtr->DynPtr->Position.vz;
return IsThisObjectVisibleFromThisPosition_WithIgnore(target->SBdptr,sbPtr->SBdptr,&eyePosition,NPC_MAX_VIEWRANGE);
}
}
return(0);
}

3
src/avp/ai_sight.h Normal file
View file

@ -0,0 +1,3 @@
#define NPC_MAX_VIEWRANGE (50000)
extern int NPCCanSeeTarget(STRATEGYBLOCK *sbptr, STRATEGYBLOCK *target, int viewRange);

1512
src/avp/avpitems.cpp Normal file

File diff suppressed because it is too large Load diff

297
src/avp/avpitems.hpp Normal file
View file

@ -0,0 +1,297 @@
/*
avpitems.hpp
AvP-specific menu items
*/
#ifndef _avpitems
#define _avpitems 1
#if ( defined( __WATCOMC__ ) || defined( _MSC_VER ) )
#pragma once
#endif
#ifndef _rebmenus_hpp
#include "rebmenus.hpp"
#endif
#if UseRebMenus
#ifndef _scstring
#include "scstring.hpp"
#endif
#include "pcmenus.h"
#ifndef pldnet_h_included
#include "stratdef.h"
#include "equipmnt.h"
// needed to include pldnet.h
#include "pldnet.h"
#endif
#endif // RebMenus
#ifdef __cplusplus
///////////////////////////////////////////////////////////////////////////////
// Project-specific item types: ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Additions to the RebMenus namespace: AvP specific item types:
namespace RebMenus
{
class Item_NetworkStatus : public Item
{
public:
Item_NetworkStatus
(
OnOffAppearance theOnOffApp_New
) : Item
(
theOnOffApp_New
)
{
}
~Item_NetworkStatus()
{
}
// Process various keypresses:
OurBool Navigate( enum NavigationOp aNavOp );
// return = was message processed
void Diagnostic(OurBool bSelected) const;
// Methods relating to rendering:
void Render
(
const RenderContext& theContext,
OurBool bSelected
) const;
SizeInfo GetSizeInfo(void) const;
static TextID GetTextIDForCharacterType
(
NETGAME_CHARACTERTYPE characterType
);
};
class Item_NetworkErrorView : public Item
{
public:
Item_NetworkErrorView();
~Item_NetworkErrorView();
// Process various keypresses:
OurBool Navigate( enum NavigationOp aNavOp );
// return = was message processed
void Diagnostic(OurBool bSelected) const;
// Methods relating to rendering:
void Render
(
const RenderContext& theContext,
OurBool bSelected
) const;
SizeInfo GetSizeInfo(void) const;
private:
static SCString* GetStringForCurrentNetworkError(void);
static TextID GetTextIDForCurrentNetworkError(void);
};
class Item_VideoModeSelector : public Item
{
public:
Item_VideoModeSelector
(
OnOffAppearance theOnOffApp_New
);
// Process various keypresses:
OurBool Navigate( enum NavigationOp aNavOp );
// return = was message processed
void Diagnostic(OurBool bSelected) const;
void Render
(
const RenderContext& theContext,
OurBool bSelected
) const;
SizeInfo GetSizeInfo(void) const;
void Dec(void);
void Inc(void);
};
class Item_KeyConfig_PageView : public Item
{
// DHM 16/3/98: I make a distinction between "methods" and "effects":
// a "method" is something you use to request an "effect"
// For example you might use the "method" of the space key to request
// the effect "jump".
public:
Item_KeyConfig_PageView
(
OnOffAppearance theOnOffApp_New,
int NumEffectsPerPage_New
);
~Item_KeyConfig_PageView();
// Process various keypresses:
OurBool Navigate( enum NavigationOp aNavOp );
// return = was message processed
void Diagnostic(OurBool bSelected) const;
// Methods relating to rendering:
void Render
(
const RenderContext& theContext,
OurBool bSelected
) const;
SizeInfo GetSizeInfo(void) const;
void SetMethod(unsigned char theMethod);
static OurBool ExpectingKey(void)
{
// if this is set, then this class takes over input handling
return (pActive != NULL);
}
static void Maintain(void);
int GetPage(void) const
{
return CurrentPage_Val;
}
int GetNumPages(void) const
{
return NumPages_Val;
}
void NxtPage(void);
void PrvPage(void);
// It's a singleton class:
static Item_KeyConfig_PageView* Get(void)
{
return pSingleton;
}
static SCString* GetMethodString( unsigned char inPhysicalKey );
public:
void Selected_Hook
(
enum NavigationOp theNavOp
);
private:
static TextID GetEffectLabel( enum KeyConfigItems );
// takes an effect (e.g. jump) and returns
// a text label to use
static OurBool GetKeyLabel
(
int inPhysicalKey,
TextID& outTextID
);
// takes a physical method key and attempts to find a text
// string to use for it, returning whether it does.
// If it fails, output area is untouched
OurBool GetEffectForRowOnPage
(
int inY,
int inPage,
enum KeyConfigItems& outEffect
) const;
// returns truth if it can output a valid effect into the specified area
int GetFinalYForPage
(
int inPage
) const;
// Y on this page can range from 0 to this inclusive
private:
// Selection: only meaningful if the item as a whole is selected
int SelectionX;
// range: [0,1]
int SelectionY;
// range: [0,NumEffectsPerPage_Val)
static Item_KeyConfig_PageView* pActive;
// iff this is non-NULL, then there's one of these expecting a key
// to change the ketboard setup; change input handling accordingly
OurBool bDebounced;
const int NumEffectsPerPage_Val;
const int NumPages_Val;
int CurrentPage_Val;
// ranges from [0,NumPages_Val)
static Item_KeyConfig_PageView* pSingleton;
};
class Item_KeyConfig_Selector : public CompositeItem
{
public:
Item_KeyConfig_Selector
(
OnOffAppearance theOnOffApp_New
);
private:
};
// Some simple command classes to embed specific function calls into buttons:
class Command_KeyConfig_PrvPage : public Command
{
public:
OurBool Execute(void)
{
Item_KeyConfig_PageView :: Get() -> PrvPage();
return Yes;
}
};
class Command_KeyConfig_NxtPage : public Command
{
public:
OurBool Execute(void)
{
Item_KeyConfig_PageView :: Get() -> NxtPage();
return Yes;
}
};
};
/* End of the header ****************************************************/
#endif // __cplusplus
#endif

1820
src/avp/avppages.cpp Normal file

File diff suppressed because it is too large Load diff

164
src/avp/avppages.hpp Normal file
View file

@ -0,0 +1,164 @@
/*
avppages.hpp
*/
#ifndef _avppages
#define _avppages 1
#if ( defined( __WATCOMC__ ) || defined( _MSC_VER ) )
#pragma once
#endif
#ifndef _rebmenus_hpp
#include "rebmenus.hpp"
#endif
#if UseRebMenus
class Command_QuitProgram : public Command
{
public:
Command_QuitProgram() : Command()
{
}
OurBool Execute(void);
};
class Command_StartSoloGame : public Command
{
public:
Command_StartSoloGame
(
I_PLAYER_TYPE inPlayerType,
I_AVP_ENVIRONMENTS inStartingEnv
) : Command(),
thePlayerType(inPlayerType),
theStartingEnv(inStartingEnv)
{
}
OurBool Execute(void);
private:
const I_PLAYER_TYPE thePlayerType;
const I_AVP_ENVIRONMENTS theStartingEnv;
};
class Command_Multiplayer : public Command
{
public:
Command_Multiplayer() : Command()
{
}
OurBool Execute(void);
// Only takes effect if the flag's been set (and clears the flag)
// Triggers the multiplayer dialog boxes
static void EndOfMenuLoopProcessing(void);
private:
static OurBool bTriggerMenuDialog;
};
class Command_ExitCurrentGame : public Command
{
public:
Command_ExitCurrentGame() : Command()
{
}
OurBool Execute(void);
};
namespace RebMenus
{
class Page_NoMenu : public Page
{
public:
Page_NoMenu();
};
class Page_Initial : public Page
{
public:
Page_Initial();
};
class Page_ChooseCharacter : public Page
{
public:
Page_ChooseCharacter();
};
class Page_Options : public Page
{
public:
Page_Options();
};
class Page_VideoOptions : public Page
{
public:
Page_VideoOptions();
private:
void Hook_LeavingPage(void);
};
class Page_AudioOptions : public Page
{
public:
Page_AudioOptions();
};
class Page_LevelsOfDetail : public Page
{
public:
Page_LevelsOfDetail();
};
class Page_MarineBriefing : public Page
{
public:
Page_MarineBriefing();
};
class Page_PredatorBriefing : public Page
{
public:
Page_PredatorBriefing();
};
class Page_AlienBriefing : public Page
{
public:
Page_AlienBriefing();
};
class Page_LoadGame : public Page
{
public:
Page_LoadGame();
};
class Page_InputOptions : public Page
{
public:
Page_InputOptions();
private:
void Hook_LeavingPage(void);
};
class Page_ConfigMouse : public Page
{
public:
Page_ConfigMouse();
};
class Page_PlaceholderMultiplayer : public Page
{
public:
Page_PlaceholderMultiplayer();
private:
void Hook_EnteringPage(void);
void Hook_LeavingPage(void);
};
class Page_MultiplayerErrorScreen : public Page
{
public:
Page_MultiplayerErrorScreen();
};
}; // namespace RebMenus
#endif // UseRebMenus
/* End of the header ****************************************************/
#endif

1019
src/avp/avpview.c Normal file

File diff suppressed because it is too large Load diff

7
src/avp/avpview.h Normal file
View file

@ -0,0 +1,7 @@
/* KJL 10:49:41 04/21/97 - avpview.h */
extern void AvpShowViews(void);
extern void InitCameraValues(void);
extern void LightSourcesInRangeOfObject(DISPLAYBLOCK *dptr);
extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;

1720
src/avp/bh_agun.c Normal file

File diff suppressed because it is too large Load diff

87
src/avp/bh_agun.h Normal file
View file

@ -0,0 +1,87 @@
// RWH - the autogun code
/* CDF 25/7/98 - Heaven help us. */
extern void AutoGunBehaveFun(STRATEGYBLOCK* ag_sbptr);
extern void AutoGunBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
//extern void CreatePlayerAutogun(void);
void MakeSentrygunNear(STRATEGYBLOCK *sbPtr);
void MakeSentrygunFar(STRATEGYBLOCK *sbPtr);
int AGunSight_FrustrumReject(VECTORCH *localOffset);
void AGunIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,VECTORCH *incoming);
typedef enum {
I_disabled,
I_tracking,
I_inactive,
}AG_STATE;
typedef struct autogun_behaviour_block
{
AG_STATE behaviourState;
int stateTimer;
HMODELCONTROLLER HModelController;
DELTA_CONTROLLER *gun_pan;
DELTA_CONTROLLER *gun_tilt;
STRATEGYBLOCK *Target;
char Target_SBname[SB_NAME_LENGTH];
/* A level of indirection for better control. */
VECTORCH targetTrackPos;
int Gun_Pan;
int Gun_Tilt;
DISPLAYBLOCK *GunFlash;
int incidentFlag;
int incidentTimer;
int ammo;
int roundsFired;
int volleyFired;
int soundHandle;
int soundHandle2;
int Firing;
int WhirrSoundOn;
int Drama;
unsigned int createdByPlayer:1;
unsigned int gunpandir :1;
unsigned int guntiltdir :1;
unsigned int IAmFar :1;
unsigned int OnTarget :1;
unsigned int OnTarget_LastFrame :1;
char death_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
}AUTOGUN_STATUS_BLOCK;
typedef struct autogun_tools_template
{
VECTORCH position;
EULER orientation;
int ammo;
int shapenum;
int startInactive;
char nameID[SB_NAME_LENGTH];
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
}AUTOGUN_TOOLS_TEMPLATE;
#define SGUN_PITCH_GIMBALL (1024)
#define SGUN_PAN_GIMBALL (1024)
#define AGUN_NEAR_VIEW_WIDTH 500 /* mm */
#define AGUN_ROF (30)
#define AGUN_VOLLEYSIZE (15)

4062
src/avp/bh_ais.c Normal file

File diff suppressed because it is too large Load diff

238
src/avp/bh_ais.h Normal file
View file

@ -0,0 +1,238 @@
/* CDF 11/6/98 - AI support functions moved out of bh_pred. */
#ifndef _bhais_h_
#define _bhais_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------
General AI Support
-------------------------------*/
typedef struct npc_obstructionreport
{
unsigned int environment :1; /* x consecutive obstructive colls against env or indestructible object */
unsigned int destructableObject :1; /* x consecutive obstructive colls against destructible object */
unsigned int otherCharacter :1; /* single collison with other npc of same type */
unsigned int anySingleObstruction :1; /* any single collision of above types */
}NPC_OBSTRUCTIONREPORT;
typedef enum avoidance_substate {
AvSS_FreeMovement=0,
AvSS_FirstAvoidance,
AvSS_SecondAvoidance,
AvSS_ThirdAvoidance,
} AVOIDANCE_SUBSTATE;
typedef enum avoidance_return_condition {
AvRC_Clear=0,
AvRC_Avoidance,
AvRC_Failure,
} AVOIDANCE_RETURN_CONDITION;
typedef struct npc_avoidancemanager {
/* New structure for super-avoidance system - expand at will! */
VECTORCH avoidanceDirection;
VECTORCH incidenceDirection;
VECTORCH incidentPoint;
VECTORCH aggregateNormal;
int recommendedDistance;
int timer;
STRATEGYBLOCK *primaryCollision;
AVOIDANCE_SUBSTATE substate;
enum AMMO_ID ClearanceDamage;
/* Third avoidance parameters! */
int stage;
VECTORCH baseVector;
VECTORCH basePoint;
VECTORCH currentVector;
MATRIXCH rotationMatrix;
VECTORCH bestVector;
int bestDistance;
int bestStage;
} NPC_AVOIDANCEMANAGER;
#define STANDARD_AVOIDANCE_TIME (ONE_FIXED*5)
#define THIRD_AVOIDANCE_MINDIST (2000)
typedef struct npc_movementdata
{
int numObstructiveCollisions;
VECTORCH avoidanceDirn;
VECTORCH lastTarget;
VECTORCH lastVelocity;
int numReverses;
AIMODULE *lastModule;
}NPC_MOVEMENTDATA;
typedef struct npc_wanderdata
{
int currentModule;
VECTORCH worldPosition;
}NPC_WANDERDATA;
#define NPC_AVOIDTIME (ONE_FIXED<<1)
#define NPC_GMD_NOPOLY (-1)
#define NPC_MIN_MOVEFROMPOLYDIST (650)
#define NPC_IMPEDING_COL_THRESHOLD (10) /* Was 10 */
#define NPC_JUMPSPEED (55) /* mm/s */
#define NPC_JUMPHEIGHT (1000)
//#define NPC_TURNRATE (ONE_FIXED) /* thro' 360 degrees */
#define NPC_TURNRATE (4096)
#define NPC_DEATHTIME (ONE_FIXED>>1)
#define NPC_TARGETPOINTELEVATION (-400)
#define NPC_INANIMATEOBJECTDAMAGE (10000)
#define NPC_NOWANDERMODULE (-1)
#define NPC_BIMBLINGINMODULE (-2)
#define NUM_ATTACKFLAGS (3)
/* Death Structures */
typedef struct hit_facing {
int Front: 1;
int Back: 1;
int Left: 1;
int Right: 1;
} HIT_FACING;
typedef struct death_data {
int Sequence_Type;
int Sub_Sequence;
int TweeningTime;
int Sequence_Length;
int Multiplayer_Code;
int Unique_Code; //unique across all deaths - for saving
int wound_flags; /* HModel wound flags */
int priority_wounds;
int Template: 1;
HIT_FACING Facing;
int Burning: 1;
int Electrical: 1;
int Crouching: 1;
int MinorBoom: 1;
int MajorBoom: 1;
} DEATH_DATA;
typedef struct attack_data {
int Sequence_Type;
int Sub_Sequence;
int TweeningTime;
int Sequence_Length;
int Multiplayer_Code;
int Unique_Code; //unique across all attacks - for saving
int wound_flags;
enum AMMO_ID flag_damage[NUM_ATTACKFLAGS];
int Crouching: 1;
int Pouncing: 1;
} ATTACK_DATA;
typedef enum movement_data_index {
MDI_Marine_Mooch_Bored=0,
MDI_Marine_Mooch_Alert,
MDI_Marine_Combat,
MDI_Marine_Sprint,
MDI_Civilian_Mooch_Bored,
MDI_Civilian_Mooch_Alert,
MDI_Civilian_Combat,
MDI_Civilian_Sprint,
MDI_Predator,
MDI_Casual_Predator,
MDI_Xenoborg,
MDI_End,
} MOVEMENT_DATA_INDEX;
typedef struct movement_data {
MOVEMENT_DATA_INDEX index;
unsigned int maxSpeed;
unsigned int acceleration;
} MOVEMENT_DATA;
/* Function Declarations */
extern int CheckAdjacencyValidity(AIMODULE *target,AIMODULE *source,int alien);
extern int AIModuleIsVisible(AIMODULE *aimodule);
extern int NPC_IsDead(STRATEGYBLOCK *sbPtr);
extern void NPC_InitMovementData(NPC_MOVEMENTDATA *moveData);
extern void NPC_IsObstructed(STRATEGYBLOCK *sbPtr, NPC_MOVEMENTDATA *moveData, NPC_OBSTRUCTIONREPORT *details, STRATEGYBLOCK **destructableObject);
extern int NPC_CannotReachTarget(NPC_MOVEMENTDATA *moveData, VECTORCH* thisTarget, VECTORCH* thisVelocity);
extern void NPCGetAvoidanceDirection(STRATEGYBLOCK *sbPtr, VECTORCH *velocityDirection, NPC_OBSTRUCTIONREPORT *details);
extern void NPCGetTargetPosition(VECTORCH *targetPoint,STRATEGYBLOCK *target);
extern int NPCSetVelocity(STRATEGYBLOCK *sbPtr, VECTORCH* targetDirn, int in_speed);
extern int NPCOrientateToVector(STRATEGYBLOCK *sbPtr, VECTORCH *zAxisVector, int turnspeed, VECTORCH *offset);
extern void NPCGetMovementTarget(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target, VECTORCH *targetPosition, int* targetIsAirduct,int alien);
extern void NPCGetMovementDirection(STRATEGYBLOCK *sbPtr, VECTORCH *velocityDirection, VECTORCH* target, WAYPOINT_MANAGER *waypointManager);
extern int FindMyFloorPoly(VECTORCH* currentPosition, MODULE* currentModule);
extern void NPC_InitWanderData(NPC_WANDERDATA *wanderData);
extern void NPC_FindWanderTarget(STRATEGYBLOCK *sbPtr, NPC_WANDERDATA *wanderData, NPC_MOVEMENTDATA *moveData);
extern void NPC_FindAIWanderTarget(STRATEGYBLOCK *sbPtr, NPC_WANDERDATA *wanderData, NPC_MOVEMENTDATA *moveData, int alien);
extern void ProjectNPCShot(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target, VECTORCH *muzzlepos, MATRIXCH *muzzleorient,enum AMMO_ID AmmoID, int multiple);
extern void CastLOSProjectile(STRATEGYBLOCK *sbPtr, VECTORCH *muzzlepos, VECTORCH *in_shotvector, enum AMMO_ID AmmoID, int multiple, int inaccurate);
extern int VerifyHitShot(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target, VECTORCH *muzzlepos, VECTORCH *in_shotvector, enum AMMO_ID AmmoID, int multiple, int maxrange);
extern AIMODULE *GetNextModuleForLink(AIMODULE *source,AIMODULE *target,int max_depth,int alien);
extern AIMODULE *GetNextModuleForLink_Core(AIMODULE *source,AIMODULE *target,int max_depth,int visibility_check,int alien);
extern int GetNextModuleInPath(int current_module, int path);
extern AIMODULE *TranslatePathIndex(int current_module, int path);
extern int GetClosestStepInPath(int path,MODULE* current_module);
extern DEATH_DATA *GetDeathSequence(HMODELCONTROLLER *controller,SECTION *TemplateRoot,DEATH_DATA *FirstDeath,int wound_flags,int priority_wounds,
int hurtiness,HIT_FACING *facing,int burning,int crouching,int electrical);
extern DEATH_DATA *GetAlienDeathSequence(HMODELCONTROLLER *controller,SECTION *TemplateRoot,int wound_flags,int priority_wounds,
int hurtiness,HIT_FACING *facing,int burning,int crouching,int electrical);
extern DEATH_DATA *GetMarineDeathSequence(HMODELCONTROLLER *controller,SECTION *TemplateRoot,int wound_flags,int priority_wounds,
int hurtiness,HIT_FACING *facing,int burning,int crouching,int electrical);
extern DEATH_DATA *GetPredatorDeathSequence(HMODELCONTROLLER *controller,SECTION *TemplateRoot,int wound_flags,int priority_wounds,
int hurtiness,HIT_FACING *facing,int burning,int crouching,int electrical);
extern DEATH_DATA *GetXenoborgDeathSequence(HMODELCONTROLLER *controller,SECTION *TemplateRoot,int wound_flags,int priority_wounds,
int hurtiness,HIT_FACING *facing,int burning,int crouching,int electrical);
extern DEATH_DATA *GetThisDeath_FromCode(HMODELCONTROLLER *controller,DEATH_DATA *FirstDeath,int code);
extern DEATH_DATA *GetThisDeath_FromUniqueCode(int code);
extern ATTACK_DATA *GetThisAttack_FromCode(HMODELCONTROLLER *controller,ATTACK_DATA *FirstAttack,int code);
extern ATTACK_DATA *GetAttackSequence(HMODELCONTROLLER *controller,ATTACK_DATA *FirstAttack,int wound_flags,int crouching, int pouncing);
extern ATTACK_DATA *GetAlienAttackSequence(HMODELCONTROLLER *controller,int wound_flags,int crouching);
extern ATTACK_DATA *GetAlienPounceAttack(HMODELCONTROLLER *controller,int wound_flags,int crouching);
extern ATTACK_DATA *GetWristbladeAttackSequence(HMODELCONTROLLER *controller,int wound_flags,int crouching);
extern ATTACK_DATA *GetPredStaffAttackSequence(HMODELCONTROLLER *controller,int wound_flags,int crouching);
extern ATTACK_DATA *GetThisAttack_FromUniqueCode(int code);//for loading
extern AIMODULE *NearNPC_GetTargetAIModuleForRetreat(STRATEGYBLOCK *sbPtr, NPC_MOVEMENTDATA *moveData);
extern AIMODULE *General_GetAIModuleForRetreat(STRATEGYBLOCK *sbPtr,AIMODULE *fearModule,int max_depth);
/* All New Avoidance Code! */
extern int New_NPC_IsObstructed(STRATEGYBLOCK *sbPtr, NPC_AVOIDANCEMANAGER *manager);
extern void Initialise_AvoidanceManager(STRATEGYBLOCK *sbPtr, NPC_AVOIDANCEMANAGER *manager);
extern AVOIDANCE_RETURN_CONDITION AllNewAvoidanceKernel(STRATEGYBLOCK *sbPtr,NPC_AVOIDANCEMANAGER *manager);
/* All New Avoidance Code! */
extern MOVEMENT_DATA *GetThisMovementData(MOVEMENT_DATA_INDEX index);
extern void AlignVelocityToGravity(STRATEGYBLOCK *sbPtr,VECTORCH *velocity);
extern int NPC_targetIsPlayer;
extern VECTORCH NPC_movementTarget;
extern int *NPC_myPoly;
extern int *NPC_myLastPoly;
extern int *NPC_lastFrameModule;
extern int Observer;
typedef struct pathheader
{
int path_length;
AIMODULE** modules_in_path;
}PATHHEADER;
extern int PathArraySize;
extern PATHHEADER* PathArray;
#ifdef __cplusplus
}
#endif
#endif

2496
src/avp/bh_alien.c Normal file

File diff suppressed because it is too large Load diff

260
src/avp/bh_alien.h Normal file
View file

@ -0,0 +1,260 @@
/*--------------Patrick 7/11/96----------------
Header file for Alien AI support functions
---------------------------------------------*/
#ifndef _bhalien_h_
#define _bhalien_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_pred.h"
/*--------------------------------------------
Enum of alien behaviour states
--------------------------------------------*/
typedef enum AlienBhState
{
ABS_Wait,
ABS_Approach,
ABS_Hunt,
ABS_Wander,
ABS_Retreat,
ABS_Attack,
ABS_Avoidance,
ABS_Dying,
ABS_Pounce,
ABS_Jump,
ABS_Dormant,
ABS_Awakening,
ABS_Taunting,
}ALIEN_BHSTATE;
/*--------------------------------------------
Enum of alien animation sequences
--------------------------------------------*/
typedef enum AlienSequence
{
ASQ_Run,
ASQ_StandingAttack_Claw,
ASQ_Crawl,
ASQ_Stand,
ASQ_Crouch,
ASQ_CrouchedAttack_Claw,
ASQ_CrawlingAttack_Claw,
ASQ_RunningAttack_Claw,
ASQ_Pain,
ASQ_Jump,
/* Additions by ChrisF, 20/4/98 */
ASQ_StandingTailPoise,
ASQ_StandingTailStrike,
ASQ_CrouchedTailPoise,
ASQ_CrouchedTailStrike,
ASQ_RunningTailPoise,
ASQ_RunningTailStrike,
ASQ_CrawlingTailPoise,
ASQ_CrawlingTailStrike,
ASQ_Eat,
ASQ_Pounce,
ASQ_JumpingTailPoise,
ASQ_JumpingTailStrike,
ASQ_Taunt,
ASQ_CrouchEat,
ASQ_Scamper,
/* More additions for reversing, 8/5/98 */
ASQ_Run_Backwards,
ASQ_Crawl_Backwards,
ASQ_RunningAttack_Claw_Backwards,
ASQ_RunningTailPoise_Backwards,
ASQ_RunningTailStrike_Backwards,
ASQ_CrawlingTailPoise_Backwards,
ASQ_CrawlingTailStrike_Backwards,
ASQ_CrawlingAttack_Claw_Backwards,
ASQ_Scamper_Backwards,
}ALIEN_SEQUENCE;
#include "sequnces.h"
typedef enum AlienMissions {
AM_UndefinedBehaviour, // Should do nothing.
AM_Hunt,
AM_GlobalHunt,
} ALIEN_MISSION;
typedef enum AlienType {
AT_Standard=0,
AT_Predalien,
AT_Praetorian,
} ALIEN_TYPE;
/*--------------------------------------------
Alien behaviour data block
--------------------------------------------*/
typedef struct alienStatusBlock
{
ALIEN_TYPE Type;
signed char Health;
int GibbFactor;
int MaxSpeed;
int Wounds;
int last_anim_length;
ALIEN_BHSTATE BehaviourState;
ATTACK_DATA *current_attack;
int PounceDetected;
int JumpDetected;
int EnablePounce;
int EnableWaypoints;
int PreferToCrouch;
MODULE *my_containing_module;
AIMODULE *huntingModule;
int incidentFlag;
int incidentTimer;
STRATEGYBLOCK *Target;
char Target_SBname[SB_NAME_LENGTH];
ALIEN_MISSION Mission;
int CurveRadius;
int CurveLength;
int CurveTimeOut;
int FarStateTimer;
int NearStateTimer;
int IAmCrouched;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
NPC_AVOIDANCEMANAGER avoidanceManager;
WAYPOINT_MANAGER waypointManager;
HMODELCONTROLLER HModelController;
char death_target_ID[SB_NAME_LENGTH]; //another strategy can be notified of the alien's death
STRATEGYBLOCK* death_target_sbptr;
STRATEGYBLOCK* generator_sbptr;//0 unless created by a generator
DPID aliensIgniterId;//Which player in a multiplayer game toasted this poor beast?
int soundHandle;
int soundHandle2;
/*The following three values are used by the extrapolation code for network games.
It doesn't particularly matter if they aren't initialised*/
int timeOfLastSend;
VECTORCH lastFacingSent;
VECTORCH lastVelocitySent;
}ALIEN_STATUS_BLOCK;
/*--------------------------------------------
Tools data template
--------------------------------------------*/
typedef struct tools_data_alien
{
struct vectorch position;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
char death_target_ID[SB_NAME_LENGTH];
ALIEN_TYPE type;
int start_inactive;
struct euler starteuler;
}TOOLS_DATA_ALIEN;
/*--------------------------------------------
Defines
--------------------------------------------*/
#define ULTRAVIOLENCE 0
#define ALIEN_STATE_PRINT 0
#define WOUNDING_SPEED_EFFECTS 1
#define ALIEN_STARTING_HEALTH (30)
#if PSX||Saturn
#define NO_OF_FRAGMENTS_FROM_DEAD_ALIEN (5)
#else
#define NO_OF_FRAGMENTS_FROM_DEAD_ALIEN (10)
#endif
/* random time between 1.5 and 2 seconds,in fixed point, with granularity 1/32th second */
#if ULTRAVIOLENCE
#define ALIEN_FAR_MOVE_TIME ((48+(FastRandom()&0xF))*(ONE_FIXED>>7))
#else
#define ALIEN_FAR_MOVE_TIME ((48+(FastRandom()&0xF))*(ONE_FIXED>>5))
#endif
/* random time between 1.5 and 2 seconds,in fixed point, with granularity 1/32th second */
#define ALIEN_FAR_RETREAT_TIME ((48+(FastRandom()&0xF))*(ONE_FIXED>>5))
#define ALIEN_JUMPVELOCITY (8000)
#define ALIEN_FORWARDVELOCITY (12000)
#define ALIEN_CURVEDISTANCE (8000)
#define ALIEN_ATTACKDISTANCE_MIN (2000)
/* Above (1500) for Ken: reduced from 2000 */
/* 1/6/98, changed back to 2000. It was well bust. */
#define ALIEN_ATTACKDISTANCE_MAX (4000)
#define ALIEN_ATTACKRANGE (3000)
/* Range check for damage validity. */
#define ALIEN_ATTACKTIME (ONE_FIXED>>1)
/* random time between 1 and 2 seconds,in fixed point,with granularity 1/8th second */
#define ALIEN_NEARWAITTIME (ONE_FIXED+((FastRandom()&0x7)*(ONE_FIXED>>3)))
#define PREDALIEN_SPEED_FACTOR ((ONE_FIXED*8)/10)
#define PRAETORIAN_SPEED_FACTOR ((ONE_FIXED*8)/10)
#define PRAETORIAN_WALKSPEED_FACTOR ((ONE_FIXED*6)/5)
#define PRAETORIAN_CRAWLSPEED_FACTOR (ONE_FIXED*2)
#define ALIEN_POUNCE_MAXRANGE (12000)
#define ALIEN_POUNCE_STARTMAXRANGE (8000)
#define ALIEN_POUNCE_MINRANGE (3000)
#define ALIEN_JUMP_SPEED (25000)
#define PREDALIEN_JUMP_SPEED (25000)
#define PRAETORIAN_JUMP_SPEED (25000)
#define ALIEN_JUMPINESS (13106)
#define PREDALIEN_JUMPINESS (13106)
#define PRAETORIAN_JUMPINESS (13106)
#define ALIEN_MASS (160)
#define PREDALIEN_MASS (200)
#define PRAETORIAN_MASS (250)
#define ALL_NEW_AVOIDANCE_ALIEN 0
/*--------------------------------------------
Prototypes
--------------------------------------------*/
void CreateAlienDynamic(STRATEGYBLOCK *Generator , ALIEN_TYPE type_of_alien);
void InitAlienBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void AlienBehaviour(STRATEGYBLOCK *sbPtr);
void AlienIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming,DISPLAYBLOCK *frag);
void MakeAlienNear(STRATEGYBLOCK *sbPtr);
void MakeAlienFar(STRATEGYBLOCK *sbPtr);
int AlienShouldBeCrawling(STRATEGYBLOCK *sbPtr);
void SetAlienShapeAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length);
void SetAlienShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime);
int AlienIsAwareOfTarget(STRATEGYBLOCK *sbPtr);
int AlienHasPathToOfTarget(STRATEGYBLOCK *sbPtr);
int GetAlienSpeedFactor(STRATEGYBLOCK *sbPtr);
int GetAlienSpeedFactor_ForSequence(STRATEGYBLOCK *sbPtr, HMODEL_SEQUENCE_TYPES sequence_type,int subsequence);
void RecomputeAlienSpeed(STRATEGYBLOCK *sbPtr);
void Alien_GoToApproach(STRATEGYBLOCK *sbPtr);
void Alien_Awaken(STRATEGYBLOCK *sbPtr);
int AlienIsCrawling(STRATEGYBLOCK *sbPtr);
#ifdef __cplusplus
}
#endif
#endif

932
src/avp/bh_binsw.c Normal file
View file

@ -0,0 +1,932 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_binsw.h"
#include "dynblock.h"
#include "dynamics.h"
#include "pldghost.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pmove.h"
#include "pvisible.h"
#include "plat_shp.h"
#include "psnd.h"
extern int NormalFrameTime;
extern int RealFrameTime;
extern int ReturnPlayerSecurityClearance(STRATEGYBLOCK *sbPtr, unsigned int securityLevel);
/*********************** SWITCH INIT *****************************/
void* BinarySwitchBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
{
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
BIN_SWITCH_TOOLS_TEMPLATE *bs_tt;
int i;
GLOBALASSERT(sbptr);
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)AllocateMem(sizeof(BINARY_SWITCH_BEHAV_BLOCK));
if (!bs_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
bs_bhv->bhvr_type = I_BehaviourBinarySwitch;
// from loaders
// 1 rest_state - on or off
// 2 mode
// 3 timer switch - time for reset
// 4 security clerance to operate
// 5 copy the target name
bs_tt = (BIN_SWITCH_TOOLS_TEMPLATE*)bhdata;
sbptr->shapeIndex = bs_tt->shape_num;
COPY_NAME(sbptr->SBname, bs_tt->nameID);
bs_bhv->bs_mode = bs_tt->mode;
bs_bhv->time_for_reset = bs_tt->time_for_reset;
bs_bhv->security_clerance = bs_tt->security_clearance;
bs_bhv->trigger_volume_min=bs_tt->trigger_volume_min;
bs_bhv->trigger_volume_max=bs_tt->trigger_volume_max;
bs_bhv->switch_flags=bs_tt->switch_flags;
bs_bhv->num_targets = bs_tt->num_targets;
if(bs_tt->num_targets)
{
bs_bhv->target_names = (SBNAMEBLOCK *)AllocateMem(sizeof(SBNAMEBLOCK) * bs_tt->num_targets);
if (!bs_bhv->target_names)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
bs_bhv->request_messages = (int *)AllocateMem(sizeof(int) * bs_tt->num_targets);
if (!bs_bhv->request_messages)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
bs_bhv->bs_targets = (STRATEGYBLOCK **)AllocateMem(sizeof(STRATEGYBLOCK *) * bs_tt->num_targets);
if (!bs_bhv->bs_targets)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
}
else
{
bs_bhv->target_names=0;
bs_bhv->request_messages=0;
bs_bhv->bs_targets=0;
}
for (i=0; i<bs_tt->num_targets; i++)
{
COPY_NAME(bs_bhv->target_names[i].name, bs_tt->target_names[i].name);
bs_bhv->request_messages[i]=bs_tt->request_messages[i];
bs_bhv->bs_targets[i] = 0;
}
if(sbptr->DynPtr) //there may be no shape
{
sbptr->DynPtr->Position = sbptr->DynPtr->PrevPosition = bs_tt->position;
sbptr->DynPtr->OrientEuler = bs_tt->orientation;
CreateEulerMatrix(&sbptr->DynPtr->OrientEuler, &sbptr->DynPtr->OrientMat);
TransposeMatrixCH(&sbptr->DynPtr->OrientMat);
}
// set up the animation control
if(sbptr->shapeIndex!=-1)
{
int item_num;
TXACTRLBLK **pptxactrlblk;
int shape_num = bs_tt->shape_num;
SHAPEHEADER *shptr = GetShapeData(shape_num);
SetupPolygonFlagAccessForShape(shptr);
pptxactrlblk = &bs_bhv->bs_tac;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
int num_seq = 0;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if (pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = bs_tt->starts_on;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num);
while(pnew_txactrlblk->tac_txarray[num_seq+1])num_seq++;
// Assert does not work at this point so
GLOBALASSERT(num_seq==2);
/* set the flags in the animation header */
// we only ever have one frame of animation per sequence -
// nb this can change talk to richard - one sequence with two frames
// or mutliple sequences???
pnew_txactrlblk->tac_txah.txa_flags |= txa_flag_play;
/* change the value held in pptxactrlblk
which point to the previous structures "next"
pointer*/
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else
{
memoryInitialisationFailure = 1;
}
}
}
*pptxactrlblk=0;
}
else
{
//no shape - so there won't be any animation
bs_bhv->bs_tac=0;
}
bs_bhv->bs_dtype = binswitch_no_display;
if (bs_bhv->bs_tac)
{
bs_bhv->bs_dtype = binswitch_animate_me;
}
bs_bhv->bs_track=bs_tt->track;
if (bs_bhv->bs_track)
{
bs_bhv->bs_track->sbptr=sbptr;
if (bs_bhv->bs_dtype == binswitch_animate_me)
{
bs_bhv->bs_dtype = binswitch_animate_and_move_me;
}
else
{
bs_bhv->bs_dtype = binswitch_move_me;
}
}
#if !Saturn
// GLOBALASSERT(bs_bhv->bs_dtype != binswitch_no_display);
#endif
// fill in the rest ourselves
bs_bhv->request = 0;
bs_bhv->state = bs_tt->starts_on;
bs_bhv->timer = 0;
bs_bhv->switch_off_message_same=bs_tt->switch_off_message_same;
bs_bhv->switch_off_message_none=bs_tt->switch_off_message_none;
bs_bhv->soundHandle = SOUND_NOACTIVEINDEX;
bs_bhv->triggered_last = No;
if(bs_bhv->bs_mode==I_bswitch_time_delay_autoexec)
{
//set request and then treat as normal time delay switch
bs_bhv->bs_mode=I_bswitch_time_delay;
bs_bhv->request=I_request_on;
}
if(bs_bhv->state)
{
bs_bhv->timer=bs_bhv->time_for_reset;
if(bs_bhv->bs_track)
{
//set the track to the end position
bs_bhv->bs_track->current_section=(bs_bhv->bs_track->num_sections-1);
bs_bhv->bs_track->timer=bs_bhv->bs_track->sections[bs_bhv->bs_track->current_section].time_for_section;
bs_bhv->bs_track->playing=1;
Update_Track_Position(bs_bhv->bs_track);
}
}
bs_bhv->TimeUntilNetSynchAllowed=0;
return((void*)bs_bhv);
}
void BinarySwitchBehaveFun(STRATEGYBLOCK* sbptr)
{
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
DISPLAYBLOCK* dptr;
int oldState;
GLOBALASSERT(sbptr);
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((bs_bhv->bhvr_type == I_BehaviourBinarySwitch));
dptr = sbptr->SBdptr;
/*
if(AvP.Network!=I_No_Network) return;
*/
/******
What I need to do - check to see if we have
a request - requests have different effects depending on
the mode - so we have to switch on the mode
*****/
if (bs_bhv->bs_dtype == binswitch_animate_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
if(dptr)
dptr->ObTxAnimCtrlBlks = bs_bhv->bs_tac;
}
if (!ReturnPlayerSecurityClearance(0,bs_bhv->security_clerance) && bs_bhv->security_clerance)
{
bs_bhv->request = I_no_request;
return;
}
if(AvP.Network != I_No_Network)
{
/*
Every time a switch is updated there is a time delay of 5 seconds before the
switch can next be changed by the host sending synch messages.
This prevents the host machine from resetting a switch before it learns that
it has been pressed
*/
if(bs_bhv->request == I_no_request)
{
bs_bhv->TimeUntilNetSynchAllowed-=RealFrameTime;
if(bs_bhv->TimeUntilNetSynchAllowed<0)
{
bs_bhv->TimeUntilNetSynchAllowed=0;
}
}
else
{
bs_bhv->TimeUntilNetSynchAllowed=5*ONE_FIXED;
}
}
if(bs_bhv->switch_flags && SwitchFlag_UseTriggerVolume)
{
/*See if switch has been set off*/
int i;
for (i=0; i<NumActiveStBlocks; i++)
{
int needToTest = 0;
STRATEGYBLOCK *sbPtr = ActiveStBlockList[i];
if (sbPtr->DynPtr)
{
if (sbPtr->SBdptr == Player)
{
needToTest = 1;
}
else if (sbPtr->I_SBtype == I_BehaviourNetGhost)
{
NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
if ((ghostData->type == I_BehaviourMarinePlayer)
||(ghostData->type == I_BehaviourAlienPlayer)
||(ghostData->type == I_BehaviourPredatorPlayer))
needToTest = 1;
}
}
if(needToTest&&
sbPtr->DynPtr->Position.vx > bs_bhv->trigger_volume_min.vx &&
sbPtr->DynPtr->Position.vx < bs_bhv->trigger_volume_max.vx &&
sbPtr->DynPtr->Position.vy > bs_bhv->trigger_volume_min.vy &&
sbPtr->DynPtr->Position.vy < bs_bhv->trigger_volume_max.vy &&
sbPtr->DynPtr->Position.vz > bs_bhv->trigger_volume_min.vz &&
sbPtr->DynPtr->Position.vz < bs_bhv->trigger_volume_max.vz)
{
bs_bhv->request=I_request_on;
break;
}
}
}
if (bs_bhv->request == I_request_on)
{
if (bs_bhv->triggered_last)
{
bs_bhv->request = I_no_request;
}
else
{
bs_bhv->triggered_last = Yes;
}
}
else
{
bs_bhv->triggered_last = No;
}
switch(bs_bhv->bs_mode)
{
case I_bswitch_timer:
{
if(bs_bhv->request == I_request_on && !bs_bhv->state)
{
bs_bhv->timer = bs_bhv->time_for_reset;
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_SWITCH1,"eh",&bs_bhv->soundHandle);
}
}
}
if (bs_bhv->bs_dtype == binswitch_move_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
// moving switch
bs_bhv->new_state = 1;
bs_bhv->new_request = 1;
bs_bhv->bs_track->reverse=0;
Start_Track_Playing(bs_bhv->bs_track);
bs_bhv->mode_store = bs_bhv->bs_mode;
bs_bhv->bs_mode = I_bswitch_moving;
}
else
{
int i;
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i], sbptr);
}
}
bs_bhv->state = 1;
}
// swap sequence
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = 1;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
}
else if(bs_bhv->timer > 0)
{
bs_bhv->timer -= NormalFrameTime;
if(bs_bhv->timer <= 0)
{
if(AvP.Network != I_No_Network)
{
bs_bhv->TimeUntilNetSynchAllowed=5*ONE_FIXED;
}
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
Sound_Play(SID_SWITCH2,"eh",&bs_bhv->soundHandle);
}
}
}
bs_bhv->state = 0;
if (bs_bhv->bs_dtype == binswitch_move_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
// moving switch
bs_bhv->new_state = 0;
bs_bhv->new_request = -1; //the 'off' message will be sent as soon as the timer finishes
bs_bhv->bs_track->reverse=1;
Start_Track_Playing(bs_bhv->bs_track);
bs_bhv->mode_store = bs_bhv->bs_mode;
bs_bhv->bs_mode = I_bswitch_moving;
}
if(!bs_bhv->switch_off_message_none)
{
//send the 'off' message
int i;
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i]^(!bs_bhv->switch_off_message_same), sbptr);
}
}
}
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = 0;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
}
}
break;
}
case I_bswitch_toggle:
{
if(bs_bhv->request == I_no_request)
return;
/* change the state and request the new state in
the target */
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
Sound_Play(SID_SWITCH1,"eh",&bs_bhv->soundHandle);
}
}
}
if(bs_bhv->bs_dtype == binswitch_move_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
// moving switch
bs_bhv->new_state = !bs_bhv->state;
if(bs_bhv->new_state)
{
bs_bhv->new_request = 1;
}
else
{
//check to see what the switch off request is
if(bs_bhv->switch_off_message_same)
bs_bhv->new_request=1;
else if(bs_bhv->switch_off_message_none)
bs_bhv->new_request=-1;
else
bs_bhv->new_request=0;
}
bs_bhv->mode_store = bs_bhv->bs_mode;
bs_bhv->bs_mode = I_bswitch_moving;
bs_bhv->bs_track->reverse=bs_bhv->state;
Start_Track_Playing(bs_bhv->bs_track);
}
else
{
bs_bhv->state = !bs_bhv->state;
{
int i;
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
if(bs_bhv->state)
{
RequestState(bs_bhv->bs_targets[i], bs_bhv->request_messages[i], sbptr);
}
else
{
if(!bs_bhv->switch_off_message_none)
{
RequestState(bs_bhv->bs_targets[i], bs_bhv->request_messages[i]^(!bs_bhv->switch_off_message_same), sbptr);
}
}
}
}
}
}
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = bs_bhv->state ;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
break;
}
case I_bswitch_wait:
{
if(bs_bhv->request == I_no_request)
return;
oldState = bs_bhv->state;
if(bs_bhv->request == I_request_on)
{
if(bs_bhv->state)
break;//switch cannot be activated again until it is reset
if(bs_bhv->bs_dtype == binswitch_move_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
// moving switch
bs_bhv->new_state = 1;
bs_bhv->new_request = 1;
bs_bhv->mode_store = bs_bhv->bs_mode;
bs_bhv->bs_mode = I_bswitch_moving;
bs_bhv->bs_track->reverse=0;
Start_Track_Playing(bs_bhv->bs_track);
}
else
{
int i;
bs_bhv->state = 1;
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i] , sbptr);
}
}
}
}
else
{
if(!bs_bhv->state) break; //can only be deactivated if currently on
if(bs_bhv->bs_dtype == binswitch_move_me || bs_bhv->bs_dtype == binswitch_animate_and_move_me)
{
// moving switch
bs_bhv->new_state = 0;
//check to see what the switch off request is
if(bs_bhv->switch_off_message_same)
bs_bhv->new_request=1;
else if(bs_bhv->switch_off_message_none)
bs_bhv->new_request=-1;
else
bs_bhv->new_request=0;
bs_bhv->mode_store = bs_bhv->bs_mode;
bs_bhv->bs_mode = I_bswitch_moving;
bs_bhv->bs_track->reverse=1;
Start_Track_Playing(bs_bhv->bs_track);
}
else
{
int i;
bs_bhv->state = 0;
if(!bs_bhv->switch_off_message_none)
{
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i]^(!bs_bhv->switch_off_message_same), sbptr);
}
}
}
}
}
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if (oldState == bs_bhv->state)
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
Sound_Play(SID_SWITCH2,"eh",&bs_bhv->soundHandle);
}
}
}
else
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
Sound_Play(SID_SWITCH1,"eh",&bs_bhv->soundHandle);
}
}
}
}
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = bs_bhv->state ? 1 : 0;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
break;
}
case I_bswitch_moving:
{
Update_Track_Position(bs_bhv->bs_track);
if(!bs_bhv->bs_track->playing)
{
bs_bhv->bs_mode = bs_bhv->mode_store;
bs_bhv->state = bs_bhv->new_state;
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = bs_bhv->state ? 1 : 0;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
if (bs_bhv->new_request != -1)
{
int i;
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
if(bs_bhv->new_request)
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i] , sbptr);
else
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i]^1, sbptr);
}
}
}
}
}
break;
case I_bswitch_time_delay :
{
if(bs_bhv->timer>0)
{
bs_bhv->timer-=NormalFrameTime;
if(bs_bhv->timer<=0 || bs_bhv->request == I_request_off)
{
//time to send the request
int i;
bs_bhv->timer=0;
//only send message if we got here through the time running out
if(bs_bhv->request != I_request_off)
{
for (i=0; i<bs_bhv->num_targets; i++)
{
if (bs_bhv->bs_targets[i])
{
RequestState(bs_bhv->bs_targets[i],bs_bhv->request_messages[i] , sbptr);
}
}
}
bs_bhv->state = 0;
// swap sequence
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = 0;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
if(AvP.Network != I_No_Network)
{
bs_bhv->TimeUntilNetSynchAllowed=5*ONE_FIXED;
}
}
}
else
{
if(bs_bhv->request == I_request_on && bs_bhv->state == 0)
{
bs_bhv->timer = bs_bhv->time_for_reset;
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if (bs_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
if(!bs_bhv->bs_track || !bs_bhv->bs_track->sound)
{
Sound_Play(SID_SWITCH1,"eh",&bs_bhv->soundHandle);
}
}
}
bs_bhv->state = 1;
// swap sequence
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = 1;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbptr->shapeIndex));
}
}
}
}
break;
default:
GLOBALASSERT(2<1);
}
bs_bhv->request = I_no_request;
}
#define BINARYSWITCHSYNCH_ON 0
#define BINARYSWITCHSYNCH_OFF 1
#define BINARYSWITCHSYNCH_IGNORE 2
int BinarySwitchGetSynchData(STRATEGYBLOCK* sbPtr)
{
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
GLOBALASSERT(sbPtr);
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GLOBALASSERT((bs_bhv->bhvr_type == I_BehaviourBinarySwitch));
//don't try to synch moving switches
if(bs_bhv->bs_mode==I_bswitch_moving)
{
return BINARYSWITCHSYNCH_IGNORE;
}
if(bs_bhv->state)
return BINARYSWITCHSYNCH_ON;
else
return BINARYSWITCHSYNCH_OFF;
}
void BinarySwitchSetSynchData(STRATEGYBLOCK* sbPtr,int status)
{
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
GLOBALASSERT(sbPtr);
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GLOBALASSERT((bs_bhv->bhvr_type == I_BehaviourBinarySwitch));
if(bs_bhv->TimeUntilNetSynchAllowed>0)
{
//ignore this attempt to synch the switch
return;
}
//don't try to synch moving switches
if(bs_bhv->bs_mode==I_bswitch_moving)
{
return;
}
switch(status)
{
case BINARYSWITCHSYNCH_ON :
if(!bs_bhv->state)
{
//this switch should be on
RequestState(sbPtr,1,0);
}
break;
case BINARYSWITCHSYNCH_OFF :
if(bs_bhv->state)
{
//this switch should be off
RequestState(sbPtr,0,0);
}
break;
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct binary_switch_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BINARY_SWITCH_REQUEST_STATE request;
BOOL state;
BSWITCH_MODE bs_mode;
int timer;
BSWITCH_MODE mode_store;
BOOL new_state;
int new_request;
BOOL triggered_last;
int txanim_sequence;
}BINARY_SWITCH_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV bs_bhv
void LoadStrategy_BinarySwitch(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
BINARY_SWITCH_SAVE_BLOCK* block = (BINARY_SWITCH_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourBinarySwitch) return;
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(request)
COPYELEMENT_LOAD(state)
COPYELEMENT_LOAD(bs_mode)
COPYELEMENT_LOAD(timer)
COPYELEMENT_LOAD(mode_store)
COPYELEMENT_LOAD(new_state)
COPYELEMENT_LOAD(new_request)
COPYELEMENT_LOAD(triggered_last)
//set the texture animation sequence
if(bs_bhv->bs_tac)
{
bs_bhv->bs_tac->tac_sequence = block->txanim_sequence;
bs_bhv->bs_tac->tac_txah_s = GetTxAnimHeaderFromShape(bs_bhv->bs_tac, (sbPtr->shapeIndex));
}
//load the track position , if the switch has one
if(bs_bhv->bs_track)
{
SAVE_BLOCK_HEADER* track_header = GetNextBlockIfOfType(SaveBlock_Track);
if(track_header)
{
LoadTrackPosition(track_header,bs_bhv->bs_track);
}
}
}
void SaveStrategy_BinarySwitch(STRATEGYBLOCK* sbPtr)
{
BINARY_SWITCH_SAVE_BLOCK *block;
BINARY_SWITCH_BEHAV_BLOCK *bs_bhv;
bs_bhv = (BINARY_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(request)
COPYELEMENT_SAVE(state)
COPYELEMENT_SAVE(bs_mode)
COPYELEMENT_SAVE(timer)
COPYELEMENT_SAVE(mode_store)
COPYELEMENT_SAVE(new_state)
COPYELEMENT_SAVE(new_request)
COPYELEMENT_SAVE(triggered_last)
//get the animation sequence
if(bs_bhv->bs_tac)
{
block->txanim_sequence = bs_bhv->bs_tac->tac_sequence;
}
else
{
block->txanim_sequence = 0;
}
//save the track position , if the switch has one
if(bs_bhv->bs_track)
{
SaveTrackPosition(bs_bhv->bs_track);
}
}

152
src/avp/bh_binsw.h Normal file
View file

@ -0,0 +1,152 @@
#ifndef _bh_binsw_h_
#define _bh_binsw_h_ 1
#include "3dc.h"
#include "track.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void* BinarySwitchBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void BinarySwitchBehaveFun(STRATEGYBLOCK* sbptr);
extern int BinarySwitchGetSynchData(STRATEGYBLOCK* sbptr);
extern void BinarySwitchSetSynchData(STRATEGYBLOCK* sbptr,int status);
/******************** BinarySwitch ***********************/
// enum to decxribe how the switch works
// action is always dependent on the SB block of the target
typedef enum binary_switch_mode
{
I_bswitch_timer,
I_bswitch_wait,
I_bswitch_toggle,
I_bswitch_moving,
I_bswitch_time_delay,
I_bswitch_time_delay_autoexec,//timer starts as soon as game starts
} BSWITCH_MODE;
typedef enum binary_switch_req_states
{
I_no_request,
I_request_on,
I_request_off,
}BINARY_SWITCH_REQUEST_STATE;
typedef enum bswitch_display_types
{
binswitch_no_display,
binswitch_animate_me,
binswitch_move_me,
binswitch_animate_and_move_me,
} BSWITCH_DISPLAY_TYPES;
typedef enum bs_move_dir
{
bs_start_to_end,
bs_end_to_start,
} BS_MOVE_DIR;
// require three states for rest fso we can ignore
#define SwitchFlag_UseTriggerVolume 0x00000001 //switch triggered by walking into trigger volume
typedef struct binary_switch
{
AVP_BEHAVIOUR_TYPE bhvr_type;
BINARY_SWITCH_REQUEST_STATE request;
BOOL state;
BSWITCH_MODE bs_mode;
int num_targets;
SBNAMEBLOCK * target_names;
int * request_messages;
STRATEGYBLOCK ** bs_targets;
int time_for_reset; // constant
int timer;
// stuff for showing how the switch displays its state
BSWITCH_DISPLAY_TYPES bs_dtype;
TXACTRLBLK *bs_tac; // animations
TRACK_CONTROLLER* bs_track;
// or positions
BSWITCH_MODE mode_store;
BOOL new_state;
int new_request;
int security_clerance; // what the plyer has to be to use this switch
int switch_flags;
VECTORCH trigger_volume_min;//for switches that can be set off by walking
VECTORCH trigger_volume_max;//into a given area
int soundHandle;
BOOL triggered_last;
unsigned int switch_off_message_same:1;
unsigned int switch_off_message_none:1;
int TimeUntilNetSynchAllowed;
}BINARY_SWITCH_BEHAV_BLOCK;
typedef struct bin_switch_tools_template
{
VECTORCH position;
EULER orientation;
int mode;
int time_for_reset;
int security_clearance;
int num_targets;
SBNAMEBLOCK * target_names;
int* request_messages;
int shape_num;
char nameID[SB_NAME_LENGTH];
TRACK_CONTROLLER* track;
int switch_flags;
VECTORCH trigger_volume_min;//for switches that can be set off by walking
VECTORCH trigger_volume_max;//into a given area
unsigned int starts_on:1;
unsigned int switch_off_message_same:1;
unsigned int switch_off_message_none:1;
} BIN_SWITCH_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

128
src/avp/bh_cable.c Normal file
View file

@ -0,0 +1,128 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_cable.h"
#include "dynamics.h"
#include "pvisible.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "plat_shp.h"
extern int NormalFrameTime;
extern char *ModuleCurrVisArray;
void* PowerCableBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
POWER_CABLE_BEHAV_BLOCK* pc_bhv;
POWER_CABLE_TOOLS_TEMPLATE* pc_tt;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
pc_bhv=(POWER_CABLE_BEHAV_BLOCK*)AllocateMem(sizeof(POWER_CABLE_BEHAV_BLOCK));
if(!pc_bhv)
{
memoryInitialisationFailure = 1;
return 0;
}
pc_bhv->bhvr_type=I_BehaviourPowerCable;
pc_tt=(POWER_CABLE_TOOLS_TEMPLATE*)bhdata;
//copy stuff from tools template
COPY_NAME(sbptr->SBname, pc_tt->nameID);
pc_bhv->position = pc_tt->position;
pc_bhv->max_charge = pc_tt->max_charge;
pc_bhv->current_charge = pc_tt->current_charge;
pc_bhv->recharge_rate = pc_tt->recharge_rate;
pc_bhv->position.vy+=10; //temporarily move cable down in case rounding errors have put cable just outside of module
sbptr->containingModule=ModuleFromPosition(&(pc_bhv->position),0);
pc_bhv->position.vy-=10;
GLOBALASSERT(sbptr->containingModule);
return (void*)pc_bhv;
}
void PowerCableBehaveFun(STRATEGYBLOCK* sbptr)
{
POWER_CABLE_BEHAV_BLOCK* pc_bhv;
GLOBALASSERT(sbptr);
pc_bhv = (POWER_CABLE_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((pc_bhv->bhvr_type == I_BehaviourPowerCable));
//see if player can get health from cable
//player must be an alien
if(AvP.PlayerType==I_Alien)
{
//the cable needs to be in a near module
GLOBALASSERT(sbptr->containingModule);
if(ModuleCurrVisArray[(sbptr->containingModule->m_index)])
{
//is player close enough
int distance=VectorDistance(&Player->ObWorld,&pc_bhv->position);
if(distance<CABLE_HEALTH_DISTANCE)
{
//give the player some health
int health_gained;
int current_health;
int max_health;
NPC_DATA *NpcData;
switch (AvP.Difficulty) {
case I_Easy:
NpcData=GetThisNpcData(I_PC_Alien_Easy);
break;
default:
case I_Medium:
NpcData=GetThisNpcData(I_PC_Alien_Medium);
break;
case I_Hard:
NpcData=GetThisNpcData(I_PC_Alien_Hard);
break;
case I_Impossible:
NpcData=GetThisNpcData(I_PC_Alien_Impossible);
break;
}
LOCALASSERT(NpcData);
max_health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
current_health=Player->ObStrategyBlock->SBDamageBlock.Health;
health_gained=min(pc_bhv->current_charge,max_health-current_health);
pc_bhv->current_charge-=health_gained;
Player->ObStrategyBlock->SBDamageBlock.Health+=health_gained;
{
/* access the extra data hanging off the strategy block */
PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
GLOBALASSERT(playerStatusPtr);
playerStatusPtr->Health=Player->ObStrategyBlock->SBDamageBlock.Health;
}
}
}
}
//increase charge if currently below maximum
if(pc_bhv->current_charge<pc_bhv->max_charge)
{
if(pc_bhv->recharge_rate)
{
pc_bhv->current_charge+=MUL_FIXED(pc_bhv->recharge_rate,NormalFrameTime);
if(pc_bhv->current_charge>pc_bhv->max_charge)
{
pc_bhv->current_charge=pc_bhv->max_charge;
}
}
}
}

49
src/avp/bh_cable.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef _bh_cable_h
#define _bh_cable_h 1
#ifdef __cplusplus
extern "C" {
#endif
extern void* PowerCableBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void PowerCableBehaveFun(STRATEGYBLOCK* sbptr);
#define CABLE_HEALTH_DISTANCE 2000
typedef struct power_cable_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
char nameID[SB_NAME_LENGTH];
VECTORCH position;
int max_charge; //health value in fixed point
int current_charge; //ditto
int recharge_rate; //recharge rate per second
}POWER_CABLE_BEHAV_BLOCK;
typedef struct power_cable_tools_template
{
char nameID[SB_NAME_LENGTH];
VECTORCH position;
int max_charge;
int current_charge;
int recharge_rate;
}POWER_CABLE_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

1077
src/avp/bh_corpse.c Normal file

File diff suppressed because it is too large Load diff

67
src/avp/bh_corpse.h Normal file
View file

@ -0,0 +1,67 @@
#ifndef bh_corpse_h_included
#define bh_corpse_h_included
#ifdef __cplusplus
extern "C" {
#endif
#define CORPSE_SIGHTINGS 1
typedef struct netcorpsedatablock {
int timer;
int validityTimer;
int SoundHandle; /* Just in case. */
int SoundHandle2;
int SoundHandle3;
int SoundHandle4;
HMODELCONTROLLER HModelController;
AVP_BEHAVIOUR_TYPE Type;
HITLOCATIONTABLE *hltable;
int GibbFactor;
DEATH_DATA *This_Death;
/* If you're a predator... */
PRED_CLOAKSTATE CloakStatus;
int CloakTimer;
int destructTimer;
/* If you're a marine... */
void (*WeaponMisfireFunction)(SECTION_DATA *, int *);
SECTION_DATA *My_Gunflash_Section;
SECTION *TemplateRoot;
struct marine_weapon_data *My_Weapon;
int weapon_variable;
int Android;
int ARealMarine;
/* If you're an alien... */
int subtype;
int Wounds;
int DeathFiring :1;
}NETCORPSEDATABLOCK;
extern void Convert_Alien_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death,DAMAGE_PROFILE* damage);
extern void Convert_Predator_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death);
extern void Convert_Marine_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death);
extern void Convert_Xenoborg_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death);
extern void CorpseBehaveFun(STRATEGYBLOCK *sbPtr);
extern void MakeCorpseNear(STRATEGYBLOCK *sbPtr);
extern void MakeCorpseFar(STRATEGYBLOCK *sbPtr);
extern void CorpseIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming);
#define CORPSE_EXPIRY_TIME (ONE_FIXED*10)
#define CORPSE_VALIDITY_TIME (ONE_FIXED>>2)
#define ALIEN_DYINGTIME (ONE_FIXED*8)
#define PRED_DIETIME (ONE_FIXED*16)
#define MARINE_DYINGTIME (ONE_FIXED*16)
#define XENO_DYINGTIME (ONE_FIXED*8)
#define AGUN_DYINGTIME (ONE_FIXED*8)
#define HDEBRIS_LIFETIME (ONE_FIXED*8)
/* Was (ONE_FIXED*3)... */
#ifdef __cplusplus
}
#endif
#endif

206
src/avp/bh_deathvol.c Normal file
View file

@ -0,0 +1,206 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_deathvol.h"
#include "dynamics.h"
#include "weapons.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern int NumActiveBlocks;
extern DISPLAYBLOCK* ActiveBlockList[];
extern DAMAGE_PROFILE DeathVolumeDamage;
extern int NormalFrameTime;
void* DeathVolumeBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
DEATH_VOLUME_BEHAV_BLOCK* dv_bhv;
DEATH_VOLUME_TOOLS_TEMPLATE* dv_tt;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
dv_bhv=(DEATH_VOLUME_BEHAV_BLOCK*)AllocateMem(sizeof(DEATH_VOLUME_BEHAV_BLOCK));
if(!dv_bhv)
{
memoryInitialisationFailure = 1;
return 0;
}
dv_bhv->bhvr_type=I_BehaviourDeathVolume;
dv_tt=(DEATH_VOLUME_TOOLS_TEMPLATE*)bhdata;
//copy stuff from tools template
COPY_NAME(sbptr->SBname, dv_tt->nameID);
dv_bhv->volume_min=dv_tt->volume_min;
dv_bhv->volume_max=dv_tt->volume_max;
dv_bhv->damage_per_second=dv_tt->damage_per_second;
dv_bhv->active=dv_tt->active;
dv_bhv->collision_required=dv_tt->collision_required;
return (void*)dv_bhv;
}
void DeathVolumeBehaveFun(STRATEGYBLOCK* vol_sbptr)
{
DEATH_VOLUME_BEHAV_BLOCK* dv_bhv;
GLOBALASSERT(vol_sbptr);
dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)vol_sbptr->SBdataptr;
GLOBALASSERT((dv_bhv->bhvr_type == I_BehaviourDeathVolume));
if(dv_bhv->active)
{
int i;
STRATEGYBLOCK* sbPtr;
DYNAMICSBLOCK* dynPtr;
int miny,maxy;
for(i=0;i<NumActiveBlocks;i++)
{
//search for objects that have has a collision this frame
//(or all objects if collisions aren't required)
DISPLAYBLOCK* dptr = ActiveBlockList[i];
sbPtr=ActiveBlockList[i]->ObStrategyBlock;
if(!sbPtr) continue;
if(!sbPtr->DynPtr) continue;
dynPtr=sbPtr->DynPtr;
if(dv_bhv->collision_required)
{
if(!dynPtr->CollisionReportPtr) continue;
}
//is the object within the death volume?
//check a vertical line against the death volume's bounding box
//first check the object's centre x and centre z values against the volume
if(dptr->ObWorld.vx<dv_bhv->volume_min.vx) continue;
if(dptr->ObWorld.vx>dv_bhv->volume_max.vx) continue;
if(dptr->ObWorld.vz<dv_bhv->volume_min.vz) continue;
if(dptr->ObWorld.vz>dv_bhv->volume_max.vz) continue;
//now check the object's vertical extents for overlap with the death volume bounding box
miny=dptr->ObWorld.vy+dptr->ObMinY;
maxy=dptr->ObWorld.vy+dptr->ObMaxY;
if(max(miny,dv_bhv->volume_min.vy) > min(maxy,dv_bhv->volume_max.vy)) continue;
/*
if(dynPtr->Position.vx > dv_bhv->volume_min.vx &&
dynPtr->Position.vx < dv_bhv->volume_max.vx &&
dynPtr->Position.vz > dv_bhv->volume_min.vz &&
dynPtr->Position.vz < dv_bhv->volume_max.vz &&
dynPtr->Position.vy > dv_bhv->volume_min.vy &&
dynPtr->Position.vy < dv_bhv->volume_max.vy)
*/
{
//finally see if the object is one of the types that can be harmed by the death volume
if(sbPtr->I_SBtype==I_BehaviourAlien ||
sbPtr->I_SBtype==I_BehaviourQueenAlien ||
sbPtr->I_SBtype==I_BehaviourFaceHugger ||
sbPtr->I_SBtype==I_BehaviourPredator ||
sbPtr->I_SBtype==I_BehaviourXenoborg ||
sbPtr->I_SBtype==I_BehaviourMarine ||
sbPtr->I_SBtype==I_BehaviourSeal ||
sbPtr->I_SBtype==I_BehaviourPredatorAlien ||
sbPtr->I_SBtype==I_BehaviourAlien ||
sbPtr->I_SBtype==I_BehaviourMarinePlayer ||
sbPtr->I_SBtype==I_BehaviourPredatorPlayer ||
sbPtr->I_SBtype==I_BehaviourAlienPlayer)
{
extern DPID myNetworkKillerId;
extern DPID AVPDPNetID;
//this is a neutral source of damage (for cooperative multiplayer games)
myNetworkKillerId = 0;
if(dv_bhv->damage_per_second)
{
//all new damage volumes.
VECTORCH direction={0,-ONE_FIXED,0};
DAMAGE_PROFILE damage = DeathVolumeDamage;
damage.Penetrative = dv_bhv->damage_per_second;
CauseDamageToObject(sbPtr,&damage,NormalFrameTime,&direction);
}
else
{
//kill the creature/player
VECTORCH direction={0,-ONE_FIXED,0};
CauseDamageToObject(sbPtr,&certainDeath,ONE_FIXED,&direction);
}
//reset network killer id
myNetworkKillerId = AVPDPNetID;
}
}
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct death_volume_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BOOL active;
}DEATH_VOLUME_SAVE_BLOCK;
void LoadStrategy_DeathVolume(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
DEATH_VOLUME_BEHAV_BLOCK* dv_bhv;
DEATH_VOLUME_SAVE_BLOCK* block = (DEATH_VOLUME_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourDeathVolume) return;
dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
dv_bhv->active = block->active;
}
void SaveStrategy_DeathVolume(STRATEGYBLOCK* sbPtr)
{
DEATH_VOLUME_SAVE_BLOCK *block;
DEATH_VOLUME_BEHAV_BLOCK* dv_bhv;
dv_bhv = (DEATH_VOLUME_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
block->active = dv_bhv->active;
}

45
src/avp/bh_deathvol.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef _bh_deathvol_h
#define _bh_deathvol_h 1
#ifdef __cplusplus
extern "C" {
#endif
extern void* DeathVolumeBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void DeathVolumeBehaveFun(STRATEGYBLOCK* sbptr);
typedef struct death_volume_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH volume_min;
VECTORCH volume_max;
unsigned int damage_per_second; //0 means infinite damage (a proper death volume - bwa ha ha.)
unsigned int active :1;
unsigned int collision_required :1;
}DEATH_VOLUME_BEHAV_BLOCK;
typedef struct death_volume_tools_template
{
char nameID[SB_NAME_LENGTH];
VECTORCH volume_min;
VECTORCH volume_max;
unsigned int damage_per_second;
unsigned int active :1;
unsigned int collision_required :1;
}DEATH_VOLUME_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

1867
src/avp/bh_debri.c Normal file

File diff suppressed because it is too large Load diff

48
src/avp/bh_debri.h Normal file
View file

@ -0,0 +1,48 @@
typedef struct OneShotAnimBehaviourType
{
int counter;
TXACTRLBLK *tac_os;
} ONESHOT_ANIM_BEHAV_BLOCK;
typedef struct SmokeGenBehaviourType
{
int counter;
int smokes;
} SMOKEGEN_BEHAV_BLOCK;
typedef struct HierarchicalDebrisBehaviourType {
int counter;
int smokes;
int GibbFactor;
int Android;
HMODELCONTROLLER HModelController;
/* behaviour type of parent object, e.g. I_BehaviourAlien */
AVP_BEHAVIOUR_TYPE Type;
int SubType;
/* Silly stuff for bouncing sounds. */
int bouncelastframe;
enum soundindex Bounce_Sound;
} HDEBRIS_BEHAV_BLOCK;
// extern functions
extern DISPLAYBLOCK *MakeDebris(AVP_BEHAVIOUR_TYPE bhvr, VECTORCH *positionPtr);
extern DISPLAYBLOCK *MakeHierarchicalDebris(STRATEGYBLOCK *parent_sbPtr,SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation, int *wounds, int speed);
extern void Pop_Section(STRATEGYBLOCK *sbPtr,SECTION_DATA *section_data, VECTORCH *blastcentre, int *wounds);
extern void CreateShapeInstance(MODULEMAPBLOCK *mmbptr, char *shapeNamePtr);
extern void OneShotBehaveFun(STRATEGYBLOCK* sptr);
extern void OneShot_Anim_BehaveFun(STRATEGYBLOCK* sptr);
extern void MakeFragments (STRATEGYBLOCK *sbptr);
#define EXPLOSION_LIFETIME (ONE_FIXED/4)
#define EXPLOSION_ANIM_SPEED (ONE_FIXED*16)
#define EXPLOSION_LIGHTING_SCALE (ONE_FIXED*16/3)
#if PSX || Saturn
#define NO_OF_SPRITES_IN_BIG_EXPLOSION 5
#else
#define NO_OF_SPRITES_IN_BIG_EXPLOSION 10
#endif

326
src/avp/bh_dummy.c Normal file
View file

@ -0,0 +1,326 @@
/* CDF 9/10/98 A bold new initiaitive! */
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "dynblock.h"
#include "dynamics.h"
#include "weapons.h"
#include "comp_shp.h"
#include "inventry.h"
#include "triggers.h"
#include "mslhand.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pmove.h"
#include "pvisible.h"
#include "bh_swdor.h"
#include "bh_plift.h"
#include "load_shp.h"
#include "bh_weap.h"
#include "bh_debri.h"
#include "lighting.h"
#include "bh_lnksw.h"
#include "bh_binsw.h"
#include "pheromon.h"
#include "bh_pred.h"
#include "bh_agun.h"
#include "plat_shp.h"
#include "psnd.h"
#include "AI_Sight.h"
#include "sequnces.h"
#include "huddefs.h"
#include "ShowCmds.h"
#include "sfx.h"
#include "bh_marin.h"
#include "bh_dummy.h"
#include "bh_far.h"
#include "pldghost.h"
#include "pheromon.h"
#include "targeting.h"
#include "dxlog.h"
#include "los.h"
#include "psndplat.h"
#include "extents.h"
#if SupportWindows95
/* for win95 net game support */
#include "pldghost.h"
#include "pldnet.h"
#endif
extern int NormalFrameTime;
extern unsigned char Null_Name[8];
extern ACTIVESOUNDSAMPLE ActiveSounds[];
extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
void CreateDummy(VECTORCH *Position);
/* Begin code! */
void CastDummy(void) {
#define BOTRANGE 2000
VECTORCH position;
if (AvP.Network!=I_No_Network) {
NewOnScreenMessage("NO DUMMYS IN MULTIPLAYER MODE");
return;
}
position=Player->ObStrategyBlock->DynPtr->Position;
position.vx+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat31,BOTRANGE);
position.vy+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat32,BOTRANGE);
position.vz+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat33,BOTRANGE);
CreateDummy(&position);
}
void CreateDummy(VECTORCH *Position) {
STRATEGYBLOCK* sbPtr;
/* create and initialise a strategy block */
sbPtr = CreateActiveStrategyBlock();
if(!sbPtr) {
NewOnScreenMessage("FAILED TO CREATE DUMMY: SB CREATION FAILURE");
return; /* failure */
}
InitialiseSBValues(sbPtr);
sbPtr->I_SBtype = I_BehaviourDummy;
AssignNewSBName(sbPtr);
/* create, initialise and attach a dynamics block */
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_MARINE_PLAYER);
if(sbPtr->DynPtr)
{
EULER zeroEuler = {0,0,0};
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
GLOBALASSERT(dynPtr);
dynPtr->PrevPosition = dynPtr->Position = *Position;
dynPtr->OrientEuler = zeroEuler;
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
}
else
{
/* dynamics block allocation failed... */
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: DYNBLOCK CREATION FAILURE");
return;
}
sbPtr->shapeIndex = 0;
sbPtr->maintainVisibility = 1;
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
/* Initialise dummy's stats */
{
sbPtr->SBDamageBlock.Health=30000<<ONE_FIXED_SHIFT;
sbPtr->SBDamageBlock.Armour=30000<<ONE_FIXED_SHIFT;
sbPtr->SBDamageBlock.SB_H_flags.AcidResistant=1;
sbPtr->SBDamageBlock.SB_H_flags.FireResistant=1;
sbPtr->SBDamageBlock.SB_H_flags.ElectricResistant=1;
sbPtr->SBDamageBlock.SB_H_flags.PerfectArmour=1;
sbPtr->SBDamageBlock.SB_H_flags.ElectricSensitive=0;
sbPtr->SBDamageBlock.SB_H_flags.Combustability=0;
sbPtr->SBDamageBlock.SB_H_flags.Indestructable=1;
}
/* create, initialise and attach a dummy data block */
sbPtr->SBdataptr = (void *)AllocateMem(sizeof(DUMMY_STATUS_BLOCK));
if(sbPtr->SBdataptr)
{
SECTION *root_section;
DUMMY_STATUS_BLOCK *dummyStatus = (DUMMY_STATUS_BLOCK *)sbPtr->SBdataptr;
GLOBALASSERT(dummyStatus);
dummyStatus->incidentFlag=0;
dummyStatus->incidentTimer=0;
dummyStatus->HModelController.section_data=NULL;
dummyStatus->HModelController.Deltas=NULL;
switch (AvP.PlayerType) {
case I_Marine:
dummyStatus->PlayerType=I_Marine;
root_section=GetNamedHierarchyFromLibrary("hnpcmarine","marine with pulse rifle");
if (!root_section) {
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: NO HMODEL");
return;
}
Create_HModel(&dummyStatus->HModelController,root_section);
InitHModelSequence(&dummyStatus->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A,-1);
break;
case I_Alien:
dummyStatus->PlayerType=I_Alien;
root_section=GetNamedHierarchyFromLibrary("hnpcalien","alien");
if (!root_section) {
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: NO HMODEL");
return;
}
Create_HModel(&dummyStatus->HModelController,root_section);
InitHModelSequence(&dummyStatus->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Standard,-1);
break;
case I_Predator:
dummyStatus->PlayerType=I_Predator;
root_section=GetNamedHierarchyFromLibrary("hnpcpredator","pred with wristblade");
if (!root_section) {
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: NO HMODEL");
return;
}
Create_HModel(&dummyStatus->HModelController,root_section);
InitHModelSequence(&dummyStatus->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Standard,-1);
break;
}
ProveHModel_Far(&dummyStatus->HModelController,sbPtr);
if(!(sbPtr->containingModule))
{
/* no containing module can be found... abort*/
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: MODULE CONTAINMENT FAILURE");
return;
}
LOCALASSERT(sbPtr->containingModule);
MakeDummyNear(sbPtr);
NewOnScreenMessage("DUMMY CREATED");
} else {
/* no data block can be allocated */
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE DUMMY: MALLOC FAILURE");
return;
}
}
void MakeDummyNear(STRATEGYBLOCK *sbPtr)
{
extern MODULEMAPBLOCK AlienDefaultMap;
MODULE tempModule;
DISPLAYBLOCK *dPtr;
DYNAMICSBLOCK *dynPtr;
DUMMY_STATUS_BLOCK *dummyStatusPointer;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->SBdptr == NULL);
dynPtr = sbPtr->DynPtr;
dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(dummyStatusPointer);
LOCALASSERT(dynPtr);
AlienDefaultMap.MapShape = sbPtr->shapeIndex;
tempModule.m_mapptr = &AlienDefaultMap;
tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
tempModule.m_numlights = 0;
tempModule.m_lightarray = (struct lightblock *)0;
tempModule.m_extraitemdata = (struct extraitemdata *)0;
tempModule.m_dptr = NULL;
AllocateModuleObject(&tempModule);
dPtr = tempModule.m_dptr;
if(dPtr==NULL) return; /* cannot allocate displayblock, so leave far */
sbPtr->SBdptr = dPtr;
dPtr->ObStrategyBlock = sbPtr;
dPtr->ObMyModule = NULL;
/* need to initialise positional information in the new display block */
dPtr->ObWorld = dynPtr->Position;
dPtr->ObEuler = dynPtr->OrientEuler;
dPtr->ObMat = dynPtr->OrientMat;
/* zero linear velocity in dynamics block */
sbPtr->DynPtr->LinVelocity.vx = 0;
sbPtr->DynPtr->LinVelocity.vy = 0;
sbPtr->DynPtr->LinVelocity.vz = 0;
/* state and sequence initialisation */
dPtr->HModelControlBlock=&dummyStatusPointer->HModelController;
ProveHModel(dPtr->HModelControlBlock,dPtr);
/*Copy extents from the collision extents in extents.c*/
dPtr->ObMinX=-CollisionExtents[CE_MARINE].CollisionRadius;
dPtr->ObMaxX=CollisionExtents[CE_MARINE].CollisionRadius;
dPtr->ObMinZ=-CollisionExtents[CE_MARINE].CollisionRadius;
dPtr->ObMaxZ=CollisionExtents[CE_MARINE].CollisionRadius;
dPtr->ObMinY=CollisionExtents[CE_MARINE].CrouchingTop;
dPtr->ObMaxY=CollisionExtents[CE_MARINE].Bottom;
dPtr->ObRadius = 1000;
}
void MakeDummyFar(STRATEGYBLOCK *sbPtr)
{
DUMMY_STATUS_BLOCK *dummyStatusPointer;
int i;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->SBdptr != NULL);
dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(dummyStatusPointer);
/* get rid of the displayblock */
i = DestroyActiveObject(sbPtr->SBdptr);
LOCALASSERT(i==0);
sbPtr->SBdptr = NULL;
/* zero linear velocity in dynamics block */
sbPtr->DynPtr->LinVelocity.vx = 0;
sbPtr->DynPtr->LinVelocity.vy = 0;
sbPtr->DynPtr->LinVelocity.vz = 0;
}
void DummyBehaviour(STRATEGYBLOCK *sbPtr) {
DUMMY_STATUS_BLOCK *dummyStatusPointer;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->containingModule);
dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(dummyStatusPointer);
/* Should be the same near as far. */
/* test if we've got a containing module: if we haven't, do nothing.
This is important as the object could have been marked for deletion by the visibility
management system...*/
if(!sbPtr->containingModule)
{
DestroyAnyStrategyBlock(sbPtr); /* just to make sure */
return;
} else if (dummyStatusPointer->PlayerType!=I_Alien) {
AddMarinePheromones(sbPtr->containingModule->m_aimodule);
}
/* Incident handling. */
dummyStatusPointer->incidentFlag=0;
dummyStatusPointer->incidentTimer-=NormalFrameTime;
if (dummyStatusPointer->incidentTimer<0) {
dummyStatusPointer->incidentFlag=1;
dummyStatusPointer->incidentTimer=32767+(FastRandom()&65535);
}
}

34
src/avp/bh_dummy.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef _bhdummy_h_
#define _bhdummy_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_ais.h"
typedef struct dummyStatusBlock {
I_PLAYER_TYPE PlayerType;
int incidentFlag;
int incidentTimer;
HMODELCONTROLLER HModelController;
} DUMMY_STATUS_BLOCK;
extern void MakeDummyNear(STRATEGYBLOCK *sbPtr);
extern void MakeDummyFar(STRATEGYBLOCK *sbPtr);
extern void DummyBehaviour(STRATEGYBLOCK *sbPtr);
#ifdef __cplusplus
}
#endif
#endif

255
src/avp/bh_fan.c Normal file
View file

@ -0,0 +1,255 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "track.h"
#include "bh_fan.h"
#include "dynamics.h"
#include "weapons.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "plat_shp.h"
extern int NormalFrameTime;
extern DAMAGE_PROFILE fan_damage;
void* FanBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
FAN_BEHAV_BLOCK* f_bhv;
FAN_TOOLS_TEMPLATE* f_tt;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
f_bhv=(FAN_BEHAV_BLOCK*)AllocateMem(sizeof(FAN_BEHAV_BLOCK));
if(!f_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
f_bhv->bhvr_type=I_BehaviourFan;
f_tt=(FAN_TOOLS_TEMPLATE*)bhdata;
sbptr->shapeIndex = f_tt->shape_num;
COPY_NAME(sbptr->SBname, f_tt->nameID);
GLOBALASSERT(sbptr->DynPtr);
sbptr->DynPtr->Position = sbptr->DynPtr->PrevPosition = f_tt->position;
sbptr->DynPtr->OrientEuler = f_tt->orientation;
CreateEulerMatrix(&sbptr->DynPtr->OrientEuler, &sbptr->DynPtr->OrientMat);
TransposeMatrixCH(&sbptr->DynPtr->OrientMat);
f_bhv->track=f_tt->track;
GLOBALASSERT(f_bhv->track);
f_bhv->track->sbptr=sbptr;
f_bhv->track->use_speed_mult=1;
f_bhv->speed_up_mult=f_tt->speed_up_mult;
f_bhv->slow_down_mult=f_tt->slow_down_mult;
f_bhv->fan_wind_direction=f_tt->fan_wind_direction;
f_bhv->fan_wind_strength=f_tt->fan_wind_strength;
if(f_bhv->track->playing)
{
f_bhv->speed_mult=ONE_FIXED;
f_bhv->track->speed_mult=ONE_FIXED;
f_bhv->state=fan_state_go;
}
else
{
f_bhv->speed_mult=0;
f_bhv->state=fan_state_stop;
}
//update wind speed
f_bhv->wind_speed=MUL_FIXED(f_bhv->speed_mult,f_bhv->fan_wind_strength);
return ((void*)f_bhv);
}
void FanBehaveFun(STRATEGYBLOCK* sbptr)
{
FAN_BEHAV_BLOCK *f_bhv;
GLOBALASSERT(sbptr);
f_bhv = (FAN_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((f_bhv->bhvr_type == I_BehaviourFan));
GLOBALASSERT(f_bhv->track);
// textprint("I am a fan\n");
if(f_bhv->state==fan_state_go)
{
if(f_bhv->speed_mult==0)
{
//fan just starting
Start_Track_Playing(f_bhv->track);
}
if(f_bhv->speed_mult<ONE_FIXED)
{
//fan currently accelerating
f_bhv->speed_mult+=MUL_FIXED(NormalFrameTime,f_bhv->speed_up_mult);
if(f_bhv->speed_mult>=ONE_FIXED)
{
f_bhv->speed_mult=ONE_FIXED;
}
f_bhv->track->speed_mult=f_bhv->speed_mult;
//update wind speed
f_bhv->wind_speed=MUL_FIXED(f_bhv->speed_mult,f_bhv->fan_wind_strength);
}
}
else
{
if(f_bhv->speed_mult>0)
{
//fan currently slowing down
f_bhv->speed_mult-=MUL_FIXED(NormalFrameTime,f_bhv->slow_down_mult);
if(f_bhv->speed_mult<0)
{
//fan has come to a stop
f_bhv->speed_mult=0;
Stop_Track_Playing(f_bhv->track);
}
f_bhv->track->speed_mult=f_bhv->speed_mult;
//update wind speed
f_bhv->wind_speed=MUL_FIXED(f_bhv->speed_mult,f_bhv->fan_wind_strength);
}
}
if(f_bhv->speed_mult)
{
Update_Track_Position(f_bhv->track);
}
//see if fan has hit anything
if(sbptr->DynPtr->CollisionReportPtr)
{
//don't cause damage iunless fan is going reasonably fast
if(f_bhv->speed_mult>ONE_FIXED/4)
{
COLLISIONREPORT* reportptr=sbptr->DynPtr->CollisionReportPtr;
fan_damage.Cutting=MUL_FIXED(f_bhv->speed_mult,200);
//go through all the collision reports and damage any creatures found
while(reportptr)
{
if(reportptr->ObstacleSBPtr)
{
STRATEGYBLOCK* hit_sbptr=reportptr->ObstacleSBPtr;
if(hit_sbptr->I_SBtype==I_BehaviourAlien ||
hit_sbptr->I_SBtype==I_BehaviourQueenAlien ||
hit_sbptr->I_SBtype==I_BehaviourFaceHugger ||
hit_sbptr->I_SBtype==I_BehaviourPredator ||
hit_sbptr->I_SBtype==I_BehaviourXenoborg ||
hit_sbptr->I_SBtype==I_BehaviourMarine ||
hit_sbptr->I_SBtype==I_BehaviourSeal ||
hit_sbptr->I_SBtype==I_BehaviourPredatorAlien ||
hit_sbptr->I_SBtype==I_BehaviourAlien ||
hit_sbptr->I_SBtype==I_BehaviourMarinePlayer ||
hit_sbptr->I_SBtype==I_BehaviourPredatorPlayer ||
hit_sbptr->I_SBtype==I_BehaviourAlienPlayer)
{
if(f_bhv->speed_mult==ONE_FIXED)
{
//ensure death if fan is going at full speed
CauseDamageToObject(hit_sbptr,&fan_damage,100*ONE_FIXED,&f_bhv->fan_wind_direction);
}
else
{
CauseDamageToObject(hit_sbptr,&fan_damage,NormalFrameTime,&f_bhv->fan_wind_direction);
}
}
}
reportptr=reportptr->NextCollisionReportPtr;
}
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct fan_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
FAN_STATE state;
int speed_mult; //0 to one_fixed : current speed relative to full speed
int wind_speed;//fixed point multiplier , taking the fan's current speed into account
}FAN_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV f_bhv
void LoadStrategy_Fan(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
FAN_BEHAV_BLOCK *f_bhv;
FAN_SAVE_BLOCK* block = (FAN_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourFan) return;
f_bhv = (FAN_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(state)
COPYELEMENT_LOAD(speed_mult)
COPYELEMENT_LOAD(wind_speed)
//load the track position
if(f_bhv->track)
{
SAVE_BLOCK_HEADER* track_header = GetNextBlockIfOfType(SaveBlock_Track);
if(track_header)
{
LoadTrackPosition(track_header,f_bhv->track);
}
}
}
void SaveStrategy_Fan(STRATEGYBLOCK* sbPtr)
{
FAN_SAVE_BLOCK* block;
FAN_BEHAV_BLOCK *f_bhv;
f_bhv = (FAN_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(state)
COPYELEMENT_SAVE(speed_mult)
COPYELEMENT_SAVE(wind_speed)
//save the track position
if(f_bhv->track)
{
SaveTrackPosition(f_bhv->track);
}
}

68
src/avp/bh_fan.h Normal file
View file

@ -0,0 +1,68 @@
#ifndef _bh_fan_h_
#define _bh_fan_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
void* FanBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
void FanBehaveFun(STRATEGYBLOCK* sbptr);
typedef enum fan_states
{
fan_state_go,
fan_state_stop,
}FAN_STATE;
typedef struct fan_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
FAN_STATE state;
TRACK_CONTROLLER* track;
int speed_up_mult; //one over time take to get to full speed
int slow_down_mult; //one over time take to stop
int speed_mult; //0 to one_fixed : current speed relative to full speed
VECTORCH fan_wind_direction; //normalised vector
int fan_wind_strength; //fixed point multiplier for fan at full speed
int wind_speed;//fixed point multiplier , taking the fan's current speed into account
}FAN_BEHAV_BLOCK;
typedef struct fan_tools_template
{
char nameID[SB_NAME_LENGTH];
int shape_num;
VECTORCH position;
EULER orientation;
int speed_up_mult; //one over time take to get to full speed
int slow_down_mult; //one over time take to stop
TRACK_CONTROLLER* track;
VECTORCH fan_wind_direction; //normalised vector
int fan_wind_strength; //fixed point multiplier
}FAN_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

1258
src/avp/bh_far.c Normal file

File diff suppressed because it is too large Load diff

63
src/avp/bh_far.h Normal file
View file

@ -0,0 +1,63 @@
/*------------------------Patrick 26/11/96-----------------------------
Header file for FAR AI alien behaviour
--------------------------------------------------------------------*/
#ifndef _bhfar_h_
#define _bhfar_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* enum for far alien target module status */
typedef enum fnpc_targetmodulestatus
{
NPCTM_NoEntryPoint,
NPCTM_NormalRoom,
NPCTM_AirDuct,
NPCTM_LiftTeleport,
NPCTM_ProxDoorOpen,
NPCTM_ProxDoorNotOpen,
NPCTM_LiftDoorOpen,
NPCTM_LiftDoorNotOpen,
NPCTM_SecurityDoorOpen,
NPCTM_SecurityDoorNotOpen,
} NPC_TARGETMODULESTATUS;
/* prototypes */
extern void FarAlienBehaviour(STRATEGYBLOCK *sbPtr);
extern void BuildFarModuleLocs(void);
extern void KillFarModuleLocs(void);
extern void LocateFarNPCInModule(STRATEGYBLOCK *sbPtr, MODULE *targetModule);
extern void LocateFarNPCInAIModule(STRATEGYBLOCK *sbPtr, AIMODULE *targetModule);
extern NPC_TARGETMODULESTATUS GetTargetAIModuleStatus(STRATEGYBLOCK *sbPtr, AIMODULE *targetModule, int alien);
extern AIMODULE *FarNPC_GetTargetAIModuleForHunt(STRATEGYBLOCK *sbPtr,int alien);
extern AIMODULE *FarNPC_GetTargetAIModuleForGlobalHunt(STRATEGYBLOCK *sbPtr);
extern AIMODULE *FarNPC_GetTargetAIModuleForWander(STRATEGYBLOCK *sbPtr, AIMODULE *exception, int alien);
extern AIMODULE *FarNPC_GetTargetAIModuleForRetreat(STRATEGYBLOCK *sbPtr);
extern AIMODULE *FarNPC_GetTargetAIModuleForMarineRespond(STRATEGYBLOCK *sbPtr);
extern void FarNpc_FlipAround(STRATEGYBLOCK *sbPtr);
/* this define to help stop aliens coagulating in the environment */
#if SupportWindows95
#define MAX_GENERATORNPCSPERMODULE 5
#define MAX_VISIBLEGENERATORNPCS 8 //12
#else
/* PSX & Saturn*/
#define MAX_GENERATORNPCSPERMODULE 5
#define MAX_VISIBLEGENERATORNPCS 6
#endif
#ifdef __cplusplus
}
#endif
#endif

1335
src/avp/bh_fhug.c Normal file

File diff suppressed because it is too large Load diff

112
src/avp/bh_fhug.h Normal file
View file

@ -0,0 +1,112 @@
/* Patrick 27/2/97 --------------------------------------------
Header file for facehugger support functions
-------------------------------------------------------------*/
#ifndef _bhfhug_h_
#define _bhfhug_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_pred.h"
/* ------------------------------------------------------------
Some enums
-------------------------------------------------------------*/
typedef enum FhugSequence
{
FhSQ_Run,
FhSQ_Attack,
FhSQ_Stand,
FhSQ_Jump,
}FHUG_SEQUENCE;
typedef enum FhugHModelSequence {
FhSSQ_Stand = 0,
FhSSQ_Run,
FhSSQ_Dies,
FhSSQ_Jump,
FhSSQ_Attack,
} FHUG_HMODEL_SEQUENCE;
#include "sequnces.h"
typedef enum facehugger_near_bhstate
{
FHNS_Approach,
FHNS_Attack,
FHNS_Wait,
FHNS_Avoidance,
FHNS_Dying,
FHNS_Floating,
FHNS_Jumping,
FHNS_AboutToJump,
}FACEHUGGER_NEAR_BHSTATE;
/* ------------------------------------------------------------
Some structures
-------------------------------------------------------------*/
typedef struct facehuggerStatusBlock
{
signed int health;
FACEHUGGER_NEAR_BHSTATE nearBehaviourState;
int stateTimer;
int DoomTimer;
int CurveRadius;
int CurveLength;
int CurveTimeOut;
unsigned int jumping :1;
NPC_MOVEMENTDATA moveData;
HMODELCONTROLLER HModelController;
int soundHandle;
int soundHandle2;
char death_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
}FACEHUGGER_STATUS_BLOCK;
typedef struct tools_data_facehugger
{
struct vectorch position;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
int startInactive;
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
}TOOLS_DATA_FACEHUGGER;
/* ------------------------------------------------------------
Some structures
-------------------------------------------------------------*/
#define FACEHUGGER_STARTING_HEALTH 5
#define NO_OF_FRAGMENTS_FROM_DEAD_FHUGA 10
#define FACEHUGGER_NEAR_SPEED 4000/* 8000 */
#define FACEHUGGER_JUMPSPEED 6000/* 10000 */
#define FACEHUGGER_JUMPDISTANCE 3000
#define FACEHUGGER_ATTACKYOFFSET (-300)/*300*/
#define FACEHUGGER_ATTACKZOFFSET (325)/*2000*/
#define FACEHUGGER_NEARATTACKTIME (ONE_FIXED>>2)
#define FACEHUGGER_NEARATTACKDAMAGE 10
#define FACEHUGGER_DYINGTIME (ONE_FIXED<<2)
#define FACEHUGGER_EXPIRY_TIME 5
#define FACEHUGGER_JUMP_SPEED (15000)
/* ------------------------------------------------------------
Some prototypes
-------------------------------------------------------------*/
void InitFacehuggerBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void FacehuggerBehaviour(STRATEGYBLOCK *sbPtr);
void MakeFacehuggerNear(STRATEGYBLOCK *sbPtr);
void MakeFacehuggerFar(STRATEGYBLOCK *sbPtr);
void FacehuggerIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple);
void Wake_Hugger(STRATEGYBLOCK *sbPtr);
#ifdef __cplusplus
}
#endif
#endif

1372
src/avp/bh_gener.c Normal file

File diff suppressed because it is too large Load diff

131
src/avp/bh_gener.h Normal file
View file

@ -0,0 +1,131 @@
/*----------------Patrick 15/11/96-------------------
Header for NPC generators
----------------------------------------------------*/
#ifndef _bhgenerator_h_
#define _bhgenerator_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*----------------Patrick 15/11/96-------------------
Generator behaviour data block. NB generators
have their own module ptr, as they are not included
in the visibility system.
----------------------------------------------------*/
typedef struct generatorblock
{
int PulseMarine_Wt;
int FlameMarine_Wt;
int SmartMarine_Wt;
int SadarMarine_Wt;
int GrenadeMarine_Wt;
int MinigunMarine_Wt;
int ShotgunCiv_Wt;
int PistolCiv_Wt;
int FlameCiv_Wt;
int UnarmedCiv_Wt;
int MolotovCiv_Wt;
int Alien_Wt;
int PredAlien_Wt;
int Praetorian_Wt;
int PistolMarine_Wt;
int WeightingTotal;
/* Pathfinder parameters */
/* If these values aren't -1 , then the generator produces path following creatures*/
int path;
int stepnumber;
struct vectorch Position;
int Timer;
/* generator can be switched on and off via the request state function */
int Active;
int GenerationRate; //scaled up by 100
int GenerationRateIncrease; //scaled up by 100
int RateIncreaseTimer;
int MaxGenNPCs;//limit for this generator
/*if use_own_rate_values is false then the generator will use the global
generation rates*/
unsigned int use_own_rate_values :1;
unsigned int use_own_max_npc :1;
} GENERATOR_BLOCK;
/*----------------Patrick 22/1/97-------------------
Hive enums and data structure.
Note that only one hive exists in the game.
----------------------------------------------------*/
typedef enum hive_state
{
HS_Attack,
HS_Regroup,
}HIVE_STATE;
typedef struct hive_data
{
HIVE_STATE currentState;
int numGenerators;
int hiveStateTimer;
int genRateTimer;
int maxGeneratorNPCs;
int generatorNPCsPerMinute;
int deltaGeneratorNPCsPerMinute;
BOOL AliensCanBeGenerated;
BOOL PredAliensCanBeGenerated;
BOOL PraetoriansCanBeGenerated;
} HIVE_DATA;
typedef struct hivelevelparams
{
int maxGeneratorNPCs;
int generatorNPCsPerMinute;
int deltaGeneratorNPCsPerMinute;
int hiveStateBaseTime;
} HIVELEVELPARAMS;
extern int ShowSlack;
/* prototypes */
extern void InitGenerator(void *posn, STRATEGYBLOCK *sbPtr);
extern void GeneratorBehaviour(STRATEGYBLOCK *sbPtr);
extern void InitHive(void);
extern void DoHive(void);
extern int NumGeneratorNPCsInEnv(void);
extern int NumGeneratorNPCsVisible(void);
extern void ForceAGenerator(void);
extern void ActivateHive(void);
/* defines */
#define DEFAULTHIVESTATETIME (60*ONE_FIXED)
#define MAXGENNPCS_MAX (255)
#define MAXGENNPCS_MIN (0)
#define GENSPERMINUTE_MAX (255)
#define GENSPERMINUTE_MIN (0)
#define INCREASEGENSPERMINUTE_MAX (255)
#define INCREASEGENSPERMINUTE_MIN (0)
#define GENERATORTIME_MAX (120*ONE_FIXED)
#define GENERATORTIME_MIN (3*ONE_FIXED)
/* globals */
extern HIVE_DATA NPCHive;
#ifdef __cplusplus
}
#endif
extern void GeneratorBalance_NoteAIDeath();
extern void GeneratorBalance_NotePlayerDeath();
#endif

327
src/avp/bh_ldoor.c Normal file
View file

@ -0,0 +1,327 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "weapons.h"
#include "comp_shp.h"
#include "inventry.h"
#include "triggers.h"
#include "mslhand.h"
#include "dynblock.h"
#include "dynamics.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pmove.h"
#include "pvisible.h"
#include "bh_pred.h"
#include "bh_swdor.h"
#include "bh_ldoor.h"
#include "bh_plift.h"
#include "load_shp.h"
#include "lighting.h"
#include "bh_lnksw.h"
#include "bh_binsw.h"
#include "bh_lift.h"
#include "psnd.h"
#include "savegame.h"
#if SupportWindows95
/* for win95 net game support */
#include "pldghost.h"
#endif
extern int NormalFrameTime;
void* LiftDoorBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
{
LIFT_DOOR_BEHAV_BLOCK *doorbhv;
LIFT_DOOR_TOOLS_TEMPLATE *doortt;
MORPHCTRL* morphctrl;
MORPHHEADER* morphheader;
MORPHFRAME* morphframe;
MODULE * my_mod;
doorbhv = (LIFT_DOOR_BEHAV_BLOCK*)AllocateMem(sizeof(LIFT_DOOR_BEHAV_BLOCK));
if (!doorbhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
doorbhv->bhvr_type = I_BehaviourLiftDoor;
// from loaders
doortt = (LIFT_DOOR_TOOLS_TEMPLATE*)bhdata;
// Set up a new Morph Control
morphctrl = (MORPHCTRL*)AllocateMem(sizeof(MORPHCTRL));
if (!morphctrl)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphheader = (MORPHHEADER*)AllocateMem(sizeof(MORPHHEADER));
if (!morphheader)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphframe = (MORPHFRAME*)AllocateMem(sizeof(MORPHFRAME));
if (!morphframe)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphframe->mf_shape1 = doortt->shape_open;
morphframe->mf_shape2 = doortt->shape_closed;
morphheader->mph_numframes = 1;
morphheader->mph_maxframes = ONE_FIXED;
morphheader->mph_frames = morphframe;
morphctrl->ObMorphCurrFrame = 0;
morphctrl->ObMorphFlags = 0;
morphctrl->ObMorphSpeed = 0;
morphctrl->ObMorphHeader = morphheader;
// Copy the name over
COPY_NAME (sbptr->SBname, doortt->nameID);
// Setup module ref
{
MREF mref=doortt->my_module;
ConvertModuleNameToPointer (&mref, MainSceneArray[0]->sm_marray);
my_mod = mref.mref_ptr;
}
GLOBALASSERT (my_mod);
my_mod->m_sbptr = sbptr;
sbptr->SBmoptr = my_mod;
sbptr->SBmomptr = my_mod->m_mapptr;
sbptr->SBflags.no_displayblock = 1;
doorbhv->door_state = doortt->state;
doorbhv->PDmctrl = morphctrl;
doorbhv->door_closing_speed=doortt->door_closing_speed;
doorbhv->door_opening_speed=doortt->door_opening_speed;
// all lift doors have a closed starting state except the
// one where the lift is - fill in other data
sbptr->SBmorphctrl = doorbhv->PDmctrl;
if(doorbhv->door_state == I_door_open)
{
sbptr->SBmorphctrl->ObMorphCurrFrame = 0;
OpenDoor(sbptr->SBmorphctrl, DOOR_OPENFASTSPEED);
}
else
{
GLOBALASSERT(doorbhv->door_state == I_door_closed);
sbptr->SBmorphctrl->ObMorphCurrFrame = 1;
CloseDoor(sbptr->SBmorphctrl, DOOR_CLOSEFASTSPEED);
}
doorbhv->request_state = doorbhv->door_state;
// copy data into relevant structures
sbptr->SBmorphctrl = doorbhv->PDmctrl;
if(sbptr->SBmoptr)
{
sbptr->SBmoptr->m_flags |= m_flag_open;
}
if(sbptr->SBmomptr)
{
sbptr->SBmomptr->MapMorphHeader = sbptr->SBmorphctrl->ObMorphHeader;
}
doorbhv->SoundHandle=SOUND_NOACTIVEINDEX;
return((void*)doorbhv);
}
void LiftDoorBehaveFun(STRATEGYBLOCK* sbptr)
{
LIFT_DOOR_BEHAV_BLOCK *doorbhv;
MORPHCTRL *mctrl;
DISPLAYBLOCK* dptr;
MODULE *mptr;
GLOBALASSERT(sbptr);
doorbhv = (LIFT_DOOR_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((doorbhv->bhvr_type == I_BehaviourLiftDoor));
mctrl = doorbhv->PDmctrl;
GLOBALASSERT(mctrl);
mptr = sbptr->SBmoptr;
GLOBALASSERT(mptr);
dptr = sbptr->SBdptr;
/* update morphing.... */
UpdateMorphing(mctrl);
switch(doorbhv->door_state)
{
case I_door_opening:
{
mptr->m_flags |= m_flag_open;
if(mctrl->ObMorphFlags & mph_flag_finished)
{
if (doorbhv->SoundHandle!=SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOOREND,"d",&mptr->m_world);
Sound_Stop(doorbhv->SoundHandle);
}
doorbhv->door_state = I_door_open;
}
break;
}
case I_door_closing:
{
if(mctrl->ObMorphFlags & mph_flag_finished)
{
if (doorbhv->SoundHandle!=SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOOREND,"d",&mptr->m_world);
Sound_Stop(doorbhv->SoundHandle);
}
doorbhv->door_state = I_door_closed;
mptr->m_flags &= ~m_flag_open;
}
else if(AnythingInMyModule(sbptr->SBmoptr))
{
if (doorbhv->SoundHandle==SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOORSTART,"d",&mptr->m_world);
Sound_Play(SID_DOORMID,"del",&mptr->m_world,&doorbhv->SoundHandle);
}
OpenDoor(mctrl, doorbhv->door_opening_speed);
doorbhv->door_state = I_door_opening;
mptr->m_flags |= m_flag_open;
}
break;
}
case I_door_open:
{
mptr->m_flags |= m_flag_open;
if(doorbhv->request_state == I_door_closed)
{
if (doorbhv->SoundHandle==SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOORSTART,"d",&mptr->m_world);
Sound_Play(SID_DOORMID,"del",&mptr->m_world,&doorbhv->SoundHandle);
}
CloseDoor(mctrl, doorbhv->door_closing_speed);
doorbhv->door_state = I_door_closing;
}
break;
}
case I_door_closed:
{
mptr->m_flags &= ~m_flag_open;
if(doorbhv->request_state == I_door_open)
{
if (doorbhv->SoundHandle==SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOORSTART,"d",&mptr->m_world);
Sound_Play(SID_DOORMID,"del",&mptr->m_world,&doorbhv->SoundHandle);
}
OpenDoor(mctrl, doorbhv->door_opening_speed);
doorbhv->door_state = I_door_opening;
mptr->m_flags |= m_flag_open;
}
break;
}
default:
LOCALASSERT(1==0);
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
typedef struct lift_door_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
DOOR_STATES door_state;
DOOR_STATES request_state;
//from the morph control
int ObMorphCurrFrame;
int ObMorphFlags;
int ObMorphSpeed;
}LIFT_DOOR_SAVE_BLOCK;
void LoadStrategy_LiftDoor(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
LIFT_DOOR_BEHAV_BLOCK *doorbhv;
LIFT_DOOR_SAVE_BLOCK* block = (LIFT_DOOR_SAVE_BLOCK*) header;
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(block->header.SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourLiftDoor) return;
doorbhv = (LIFT_DOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
doorbhv->request_state = block->request_state;
doorbhv->door_state = block->door_state;
doorbhv->PDmctrl->ObMorphCurrFrame = block->ObMorphCurrFrame;
doorbhv->PDmctrl->ObMorphFlags = block->ObMorphFlags;
doorbhv->PDmctrl->ObMorphSpeed = block->ObMorphSpeed;
Load_SoundState(&doorbhv->SoundHandle);
}
void SaveStrategy_LiftDoor(STRATEGYBLOCK* sbPtr)
{
LIFT_DOOR_SAVE_BLOCK *block;
LIFT_DOOR_BEHAV_BLOCK *doorbhv ;
doorbhv = (LIFT_DOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
block->request_state = doorbhv->request_state;
block->door_state = doorbhv->door_state;
block->ObMorphCurrFrame = doorbhv->PDmctrl->ObMorphCurrFrame;
block->ObMorphFlags = doorbhv->PDmctrl->ObMorphFlags;
block->ObMorphSpeed = doorbhv->PDmctrl->ObMorphSpeed;
Save_SoundState(&doorbhv->SoundHandle);
}
/*---------------------------**
** End of loading and saving **
**---------------------------*/

46
src/avp/bh_ldoor.h Normal file
View file

@ -0,0 +1,46 @@
/******************** LIFT DOORS ********************/
/*
lift doors do not have to look at the environment for
triggers. they wait for the controlling lift block to
say open or closed. EXCEPT when the door is open it
will not close if some other object is in its module
*/
typedef struct lift_door_behaviour_type
{
AVP_BEHAVIOUR_TYPE bhvr_type;
DOOR_STATES door_state;
MORPHCTRL *PDmctrl;
DOOR_STATES request_state;
int SoundHandle;
/*---- Patrick 1/1/97 -----
added for far ai stratgies
--------------------------*/
int door_opening_speed;
int door_closing_speed;
} LIFT_DOOR_BEHAV_BLOCK;
typedef struct lift_door_tools_template
{
BOOL state;
MREF my_module;
int shape_open;
int shape_closed;
char nameID[SB_NAME_LENGTH];
int door_opening_speed;
int door_closing_speed;
} LIFT_DOOR_TOOLS_TEMPLATE;
extern void* LiftDoorBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void LiftDoorBehaveFun(STRATEGYBLOCK* sbptr);

819
src/avp/bh_lift.c Normal file
View file

@ -0,0 +1,819 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "weapons.h"
#include "comp_shp.h"
#include "inventry.h"
#include "triggers.h"
#include "mslhand.h"
#include "huddefs.h"
#include "dynblock.h"
#include "dynamics.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pmove.h"
#include "pvisible.h"
#include "bh_swdor.h"
#include "load_shp.h"
#include "lighting.h"
#include "bh_lnksw.h"
#include "bh_binsw.h"
#include "bh_lift.h"
#include "psnd.h"
#if SupportWindows95
/* for win95 net game support */
#include "pldghost.h"
#endif
extern int NormalFrameTime;
// stuff for environment changing
extern void IntegrateNewEnvironment();
extern int NumActiveBlocks;
// Globals we are going to export
int RequestEnvChangeViaLift = 0;
int RequestEnvChangeViaAirlock = 0;
LIFT_CONTROL_BLOCK EC_Lift_Ctrl;
MODULE Old_Pos_Module;
static void TeleportFloorSwitches(MODULE* dest, MODULE* src, LIFT_CONTROL_BLOCK* liftCtrl);
/*********************** CLOSED TELEPORT LIFTS INIT ***************/
void * LiftBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
{
LIFT_BEHAV_BLOCK *lift_bhv;
LIFT_STATION* lift_stn;
LIFT_TOOLS_TEMPLATE* lift_tt;
MODULE * my_mod;
GLOBALASSERT(sbptr);
lift_bhv = (LIFT_BEHAV_BLOCK*)AllocateMem(sizeof(LIFT_BEHAV_BLOCK));
if(!lift_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
lift_bhv->bhvr_type = I_BehaviourLift;
lift_stn = &lift_bhv->lift_station;
lift_tt = (LIFT_TOOLS_TEMPLATE*)bhdata;
// Copy the name over
COPY_NAME (sbptr->SBname, lift_tt->nameID);
// Setup module ref if not external
if (lift_tt->environment == (int)AvP.CurrentEnv)
{
{
MREF mref=lift_tt->my_module;
ConvertModuleNameToPointer (&mref, MainSceneArray[0]->sm_marray);
my_mod = mref.mref_ptr;
}
GLOBALASSERT (my_mod);
my_mod->m_sbptr = sbptr;
sbptr->SBmoptr = my_mod;
sbptr->SBmomptr = my_mod->m_mapptr;
sbptr->SBflags.no_displayblock = 1;
}
// loaded data - first the station
COPY_NAME(lift_stn->lift_call_switch_name, lift_tt->call_switch_name);
COPY_NAME(lift_stn->lift_door_name, lift_tt->lift_door_name);
COPY_NAME(lift_stn->lift_floor_switch_name, lift_tt->lift_floor_switch_name);
COPY_NAME(lift_stn->my_sb_name, lift_tt->my_module_name);
lift_stn->env = lift_tt->environment;
lift_stn->num_floor = lift_tt->num_floor;
lift_stn->orient = lift_tt->orient;
// fill in the rest of the stn data;
lift_stn->lift_call_switch = NULL;
lift_stn->lift_door = NULL;
lift_stn->lift_floor_switch = NULL;
lift_stn->lift_module = sbptr->SBmoptr;
if(lift_tt->lift_flags & LiftFlag_Here)
lift_stn->starting_station = 1;
else
lift_stn->starting_station = 0;
lift_stn->called = 0;
// fill in the behaviour block
lift_bhv->control_sb = NULL;
lift_bhv->controller = lift_tt->controller;
COPY_NAME(lift_bhv->control_sb_name, lift_tt->control_sb_name);
if(lift_bhv->controller)
{
LIFT_CONTROL_BLOCK* lcont = AllocateMem(sizeof(LIFT_CONTROL_BLOCK));
if(!lcont)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
lift_bhv->lift_control = lcont;
// fill in the number of floors
lcont->num_stations = lift_tt->num_stations;
lcont->lift_stations = (LIFT_STATION**)AllocateMem(sizeof(LIFT_STATION*)*lcont->num_stations);
if(!lcont->lift_stations)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
//and init that array
{
int i=0;
while(i < lcont->num_stations)
{
*(lcont->lift_stations + i) = NULL;
i++;
}
}
// fill in the rest of the data
*(lcont->lift_stations + lift_stn->num_floor) = lift_stn;
lcont->dest_station = -1;
lcont->delay_at_floor = 0;
lcont->delay_between_floors = 0;
lcont->motion = I_going_down;
lcont->state = I_ls_waiting;
lcont->curr_station = -1;
lcont->prev_station = -1;
lcont->SoundHandle = SOUND_NOACTIVEINDEX;
if(lift_tt->lift_flags & LiftFlag_NoTel)
lcont->floor_switches_fixed=1;
else
lcont->floor_switches_fixed=0;
}
return((void*)lift_bhv);
}
/*************************** LIFT CONTROL *****************************/
void LiftBehaveFun(STRATEGYBLOCK* sbptr)
{
LIFT_BEHAV_BLOCK *lift_bhv;
LIFT_CONTROL_BLOCK *lift_ctrl;
LIFT_STATION *curr_stn;
I_AVP_ENVIRONMENTS dest_env;
GLOBALASSERT(sbptr);
lift_bhv = (LIFT_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((lift_bhv->bhvr_type == I_BehaviourLift));
curr_stn = &lift_bhv->lift_station;
GLOBALASSERT(curr_stn);
lift_ctrl = lift_bhv->lift_control;
/* ALL the lift modules have a Strategy block that contains inforamtion
about that particular location. Only one points to the LIFT CONTROL
BLOCK
*/
/* the lifts will work between envs as well as on the same env
so the control of the doors in the other envs sin't actually set,
but a record of the postion is maintained
*/
if(lift_bhv->controller)
{
// HACK - RWH - if this is true the data is broken and this fix won't always work
if(lift_ctrl->curr_station == -1)
lift_ctrl->curr_station = 0;
switch(lift_ctrl->state)
{
case I_ls_waiting:
{
/*** find dest and set movement direction this is always the
same even if the lift is on a different floor ***/
int lower_station = -1;
int upper_station = -1;
int i;
LIFT_STATION *lift_stn;
/**** find the nearest floors selected ****/
// search up and down
for(i = lift_ctrl->curr_station; (i >= 0) && (lower_station == -1); i --)
{
lift_stn = lift_ctrl->lift_stations[i];
if(lift_stn->called)
upper_station = i; // higher floors have lower nums
}
for(i = lift_ctrl->curr_station; (i < lift_ctrl->num_stations) && (upper_station == -1); i ++)
{
lift_stn = lift_ctrl->lift_stations[i];
if(lift_stn->called)
lower_station = i; // lower floors have higher nums
}
/****** set the destination and the motion direction ****/
if(lift_ctrl->motion == I_going_down)// higher nums
{
if(lower_station != -1)
{
lift_ctrl->dest_station = lower_station;
}
else
{
lift_ctrl->dest_station = upper_station;
lift_ctrl->motion =I_going_up;
}
}
else if(lift_ctrl->motion == I_going_up) // lower nums
{
if(upper_station != -1)
{
lift_ctrl->dest_station = upper_station;
}
else
{
lift_ctrl->dest_station = lower_station;
lift_ctrl->motion =I_going_down;
}
}
// now we have a station to go to, we start the lift in motion
// unless we have just pressed the current floor switch again
if(lift_ctrl->dest_station == lift_ctrl->curr_station)
{
// we have just called the lift to the same place
lift_ctrl->dest_station = -1;
lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
lift_stn->called = 0;
}
else if(lift_ctrl->dest_station != -1)
{
// if there is a dest, set the lift to go
// close current stations
#if PC_E3DEMO
LIFT_STATION* dest_stn = lift_ctrl->lift_stations[lift_ctrl->dest_station];
#endif
lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
#if PC_E3DEMO
if(dest_stn->env != AvP.CurrentEnv)
{
// turn off inter env lifts
NewOnScreenMessage(GetTextString(TEXTSTRING_DB_ACCESSDENIED));
RequestState(dest_stn->lift_floor_switch, 0, 0);
lift_ctrl->dest_station = -1;
dest_stn->called = 0;
}
else
#endif
{
lift_ctrl->prev_station = lift_ctrl->curr_station;
if(lift_stn->lift_door)
{
// no door - must be on another env
RequestState(lift_stn->lift_door, 0, 0);
}
lift_ctrl->state = I_ls_closing_door;
}
}
break;
}
case I_ls_closing_door:
{
// lift station for the current lift position has to
// have a closed door
BOOL door_state;
LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
MODULE* mptr;
mptr = pos_stn->lift_module;
// deal with the fact that the lift is in a different env
// same env - normal code
// called from us to another env - normal code
// called from another env to us - jump the close door
if(pos_stn->env != AvP.CurrentEnv)
{
lift_ctrl->state = I_ls_moving;
lift_ctrl->delay_between_floors = LIFT_MOVE_DELAY;
break;
}
// otherwise run normal code
// close the door before we change state to moving
door_state = GetState(pos_stn->lift_door);
if(!door_state)
{
// turn off the current lift position station call switches
// run only when pos_stn is in our own env POSSIBLE BUG -
// lift wont be called to our floor if there is an Alien in it
if(BadGuyInModuleOrNoPlayer())
{
lift_ctrl->state = I_ls_opening_door;
lift_ctrl->dest_station = -1;
lift_ctrl->delay_between_floors = -1;
RequestState(pos_stn->lift_door, 1, 0);
}
else
{
lift_ctrl->state = I_ls_moving;
lift_ctrl->delay_between_floors = LIFT_MOVE_DELAY;
RequestState(pos_stn->lift_call_switch, 0, 0);
if(pos_stn->lift_floor_switch)
RequestState(pos_stn->lift_floor_switch, 0, 0);
//what if there is a bad guy in the lift - if there is open the door
//and reset all the switches and stations
if (lift_ctrl->SoundHandle==SOUND_NOACTIVEINDEX)
{
GLOBALASSERT(mptr);
Sound_Play(SID_LIFT_START,"dh",&mptr->m_world);
Sound_Play(SID_LIFT_LOOP,"delh",&mptr->m_world, &lift_ctrl->SoundHandle);
}
}
}
break;
}
case I_ls_moving:
{
int curr_station_num = lift_ctrl->curr_station;
LIFT_STATION *pos_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
MODULE* mptr;
mptr = pos_stn->lift_module;
dest_env = lift_ctrl->lift_stations[lift_ctrl->dest_station]->env;
lift_ctrl->delay_between_floors -= NormalFrameTime;
// TRAP CHANGE OF ENVIRONMENT
// we need to trap it here so we don't have the delay
// between floors. However. The trap should make sure it is the nex array pos
if(AvP.CurrentEnv != dest_env)
{
// have to load an env - can we do it next - is the
// new env the next floor in the array??
if(lift_ctrl->motion == I_going_up)
{
curr_station_num --;
}
else
{
curr_station_num ++;
}
lift_ctrl->curr_station=curr_station_num;
if(curr_station_num == lift_ctrl->dest_station)
{
// OKAY chnage Environment VIA LIFT
// we need a copy of our current module pos
// (for the teleport), a copy of the
// SBs in our module and a copy of the lift
// control block
LIFT_STATION *lift_stn_old;
EC_Lift_Ctrl = *lift_ctrl;
lift_stn_old = EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.prev_station];
Old_Pos_Module = *lift_stn_old->lift_module;
InitPreservedSBs();
PreserveStBlocksInModule(&Old_Pos_Module);
EC_Lift_Ctrl.curr_station = curr_station_num;
RequestEnvChangeViaLift = 1;
// we now do the rest of the SBs. before we
// can chack the env - note that NOTHING can move
// into the lift now.
}
}
// else do normal code
else if((lift_ctrl->delay_between_floors < 0))
{
if(lift_ctrl->motion == I_going_up)
{
lift_ctrl->curr_station --;
}
else
{
lift_ctrl->curr_station ++;
}
LOCALASSERT(lift_ctrl->curr_station >= 0);
if(lift_ctrl->curr_station == lift_ctrl->dest_station)
{
// at destination
LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
LIFT_STATION *lift_stn_old = lift_ctrl->lift_stations[lift_ctrl->prev_station];
MODULE *new_pos, *old_pos;
new_pos = lift_stn_new->lift_module;
old_pos = lift_stn_old->lift_module;
lift_ctrl->dest_station = -1;
lift_ctrl->state = I_ls_opening_door;
/* roxby: i have taken this out - patrick */
/* GLOBALASSERT(mptr); */
Sound_Play(SID_LIFT_END,"h");
Sound_Stop(lift_ctrl->SoundHandle);
// door open
RequestState(lift_stn_new->lift_door, 1, 0);
lift_stn_new->called = 0;
if(old_pos)
{
// if we don't have an old pos, we must
// be coming from another env
TeleportContents(new_pos, old_pos,lift_ctrl->floor_switches_fixed);
}
}
else
{
// interrupt monment to stop at new floor
//this should never happen in a seperate env
LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
LIFT_STATION *lift_stn_old = lift_ctrl->lift_stations[lift_ctrl->prev_station];
MODULE* old_pos, *new_pos;
// to trap button presses when moving between floors -
// not really ness and it complecates things
old_pos = lift_stn_old->lift_module;
new_pos = lift_stn_new->lift_module;
#if 0
if(lift_stn_new->called)
{
lift_ctrl->state = I_ls_opening_door;
RequestState(lift_stn_new->lift_call_switch, 0, 0);
if(lift_stn_new->lift_floor_switch)
RequestState(lift_stn_new->lift_floor_switch, 0, 0);
RequestState(lift_stn_new->lift_door, 1, 0);
if(old_pos)
{
// if we don't have an old pos, we must
// be coming from another env
TeleportContents(new_pos, old_pos,lift_ctrl->floor_switches_fixed);
}
lift_stn_new->called = 0;
}
else
#endif
{
// futher to go - move along now
lift_ctrl->delay_between_floors += LIFT_MOVE_DELAY;
}
}
}
break;
}
case I_ls_opening_door:
{
LIFT_STATION *lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
BOOL door_state = GetState(lift_stn_new->lift_door);
if(door_state)
{
lift_ctrl->state = I_ls_delay_at_floor;
lift_ctrl->delay_at_floor = LIFT_FLOOR_DELAY;
}
break;
}
case I_ls_delay_at_floor:
{
lift_ctrl->delay_at_floor -= NormalFrameTime;
if(lift_ctrl->delay_at_floor < 0)
{
LIFT_STATION *lift_stn;
// turn on the floor lights
lift_stn = lift_ctrl->lift_stations[lift_ctrl->curr_station];
RequestState(lift_stn->lift_call_switch, 1, 0);
if(lift_stn->lift_floor_switch_name[0] || lift_stn->lift_floor_switch_name[4])
RequestState(lift_stn->lift_floor_switch, 1, 0);
lift_ctrl->state = I_ls_waiting;
lift_ctrl->dest_station = -1;
}
break;
}
default:
GLOBALASSERT(2<1);
}
}
}
// this function reposts anything that would prevent
// The palyer most be in the module and nothing
// else can be
BOOL BadGuyInModuleOrNoPlayer()
{
return(0);
}
void TeleportContents(MODULE* new_pos, MODULE* old_pos,BOOL floor_switches_fixed)
{
// 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;
int dest_max_x, dest_min_x, dest_max_y, dest_min_y, dest_max_z, dest_min_z;
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;
max_x = old_pos->m_maxx + old_pos->m_world.vx;
min_x = old_pos->m_minx + old_pos->m_world.vx;
max_y = old_pos->m_maxy + old_pos->m_world.vy;
min_y = old_pos->m_miny + old_pos->m_world.vy;
max_z = old_pos->m_maxz + old_pos->m_world.vz;
min_z = old_pos->m_minz + old_pos->m_world.vz;
dest_max_x = new_pos->m_maxx + new_pos->m_world.vx -200;
dest_min_x = new_pos->m_minx + new_pos->m_world.vx +200;
dest_max_y = new_pos->m_maxy + new_pos->m_world.vy -200;
dest_min_y = new_pos->m_miny + new_pos->m_world.vy +200;
dest_max_z = new_pos->m_maxz + new_pos->m_world.vz -200;
dest_min_z = new_pos->m_minz + new_pos->m_world.vz +200;
for(i = 0; i < NumActiveStBlocks; i++)
{
VECTORCH obj_world;
STRATEGYBLOCK *sbptr;
DYNAMICSBLOCK *dynptr;
sbptr = ActiveStBlockList[i];
if(!(dynptr = sbptr->DynPtr))
continue;
if(floor_switches_fixed)
{
if(sbptr->I_SBtype==I_BehaviourBinarySwitch || sbptr->I_SBtype==I_BehaviourLinkSwitch)
continue;
else if(sbptr->I_SBtype==I_BehaviourInanimateObject && ((INANIMATEOBJECT_STATUSBLOCK*)sbptr->SBdataptr)->typeId==0)
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)
{
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;
//make sure new location is inside destination module
if(!dynptr->IsStatic)
{
if(dynptr->Position.vx<dest_min_x) dynptr->Position.vx=dest_min_x;
if(dynptr->Position.vy<dest_min_y) dynptr->Position.vy=dest_min_y;
if(dynptr->Position.vz<dest_min_z) dynptr->Position.vz=dest_min_z;
if(dynptr->Position.vx>dest_max_x) dynptr->Position.vx=dest_max_x;
if(dynptr->Position.vy>dest_max_y) dynptr->Position.vy=dest_max_y;
if(dynptr->Position.vz>dest_max_z) dynptr->Position.vz=dest_max_z;
if(dynptr->PrevPosition.vx<dest_min_x) dynptr->PrevPosition.vx=dest_min_x;
if(dynptr->PrevPosition.vy<dest_min_y) dynptr->PrevPosition.vy=dest_min_y;
if(dynptr->PrevPosition.vz<dest_min_z) dynptr->PrevPosition.vz=dest_min_z;
if(dynptr->PrevPosition.vx>dest_max_x) dynptr->PrevPosition.vx=dest_max_x;
if(dynptr->PrevPosition.vy>dest_max_y) dynptr->PrevPosition.vy=dest_max_y;
if(dynptr->PrevPosition.vz>dest_max_z) dynptr->PrevPosition.vz=dest_max_z;
}
if(sbptr->maintainVisibility)
{
sbptr->containingModule = new_pos;
}
}
}
}
void CleanUpLiftControl()
{
// okay - we have selected a new env AND it is the
// next env in the list - lets go with the load
// we need a copu list of strat blocks that WE DO NOT
// DEALLOCATE the behaviour / dyn blocks for. We then
// reinitialise AFTER these have been inserted into the
// ActiveStBlockList
LIFT_STATION *lift_stn = EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.dest_station];
char dest_mod_name[8];
MODULE *new_pos_module;
int orient_diff;
STRATEGYBLOCK* new_loc_sbptr;
COPY_NAME(dest_mod_name, lift_stn->my_sb_name);
orient_diff = EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.dest_station]->orient
- EC_Lift_Ctrl.lift_stations[EC_Lift_Ctrl.prev_station]->orient;
// DESTROYS ALL OUR OLD DATA - ONLY OUR
// COPIES REMAIN
ChangeEnvironmentToEnv(lift_stn->env);
IntegrateNewEnvironment();
// find where we have teleported to
new_loc_sbptr = FindSBWithName(dest_mod_name);
GLOBALASSERT(new_loc_sbptr);
new_pos_module = new_loc_sbptr->SBmoptr;
// teleport the bastrads
TeleportPreservedSBsToNewEnvModule(new_pos_module, &Old_Pos_Module,orient_diff);
AddPreservedSBsToActiveList();
// find the new control block anc copy our preserved one in
// need to recalc lift_station_new
{
LIFT_BEHAV_BLOCK *lift_bhv;
LIFT_CONTROL_BLOCK *lift_ctrl;
LIFT_STATION *lift_stn_new;
lift_bhv = (LIFT_BEHAV_BLOCK*)new_loc_sbptr->SBdataptr;
GLOBALASSERT((lift_bhv->bhvr_type == I_BehaviourLift));
lift_ctrl = lift_bhv->lift_control;
GLOBALASSERT(lift_ctrl->num_stations == EC_Lift_Ctrl.num_stations);
// copy over the vital bits
lift_ctrl->curr_station = EC_Lift_Ctrl.curr_station;
lift_ctrl->prev_station = EC_Lift_Ctrl.prev_station;
lift_ctrl->motion = EC_Lift_Ctrl.motion;
// and get into the right state
lift_ctrl->state = I_ls_opening_door;
lift_ctrl->dest_station = -1;
// and get the periphs into their right states
// get the new lift station
lift_stn_new = lift_ctrl->lift_stations[lift_ctrl->curr_station];
//set all the other station switches to off to overdide
// the starting_station init in AssignAllSBNames
{
int i;
LIFT_STATION *liftStnPtr;
for(i=0; i < lift_ctrl->num_stations; i++)
{
liftStnPtr = lift_ctrl->lift_stations[i];
if(liftStnPtr->env == AvP.CurrentEnv)
{
RequestState(liftStnPtr->lift_call_switch, 0, 0);
RequestState(liftStnPtr->lift_floor_switch, 0, 0);
RequestState(liftStnPtr->lift_door, 0, 0);
}
}
}
// set our current stations periphs into the correct
// state
RequestState(lift_stn_new->lift_call_switch, 1, 0);
RequestState(lift_stn_new->lift_floor_switch, 1, 0);
RequestState(lift_stn_new->lift_door, 1, 0);
TeleportFloorSwitches
(
lift_stn_new->lift_module,
lift_stn_new->lift_floor_switch->containingModule,
lift_ctrl
);
InitPreservedSBs();
UpdateWeaponShape(); // so we get the correct shape in the MSL
}
}
static void TeleportFloorSwitches
(
MODULE* dest,
MODULE* src,
LIFT_CONTROL_BLOCK * liftCtrl
)
{
if(dest != src)
{
TeleportContents(dest, src, 0);
}
}

116
src/avp/bh_lift.h Normal file
View file

@ -0,0 +1,116 @@
extern void LiftBehaveFun(STRATEGYBLOCK* sbptr);
extern void * LiftBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void CleanUpLiftControl();
extern void TeleportContents(MODULE* new_pos, MODULE* old_pos,BOOL floor_switches_fixed);
extern BOOL BadGuyInModule();
/*********************** Lifts **************************/
typedef struct lift_stations
{
char lift_call_switch_name[SB_NAME_LENGTH];
STRATEGYBLOCK* lift_call_switch;
char lift_door_name[SB_NAME_LENGTH];
STRATEGYBLOCK* lift_door;
char lift_floor_switch_name[SB_NAME_LENGTH];
STRATEGYBLOCK* lift_floor_switch; // the floor switches teleport
BOOL called;
char my_sb_name[SB_NAME_LENGTH]; // only used when envs change
MODULE* lift_module;
I_AVP_ENVIRONMENTS env; // tells us if we need a cd load
int num_floor; // not the floor num but the poition
// in the array
int orient; //the facing of the lift (from 0 to 3)
BOOL starting_station;
}LIFT_STATION;
typedef enum liftmotion{
I_going_up, /*** numbers go down (0 at surface **/
I_going_down, // numbers go up
}LIFT_MOTION;
typedef enum lift_ctrl_states
{
I_ls_waiting,
I_ls_closing_door,
I_ls_moving,
I_ls_opening_door,
I_ls_delay_at_floor,
}LIFT_CTRL_STATES;
#define LIFT_FLOOR_DELAY ONE_FIXED*2 // two secs
#define LIFT_MOVE_DELAY ONE_FIXED*5 // three secs
typedef struct lift_control
{
int num_stations; // num staions for this lift
LIFT_STATION** lift_stations; // array of lift stations for this lift
int dest_station; // -1 when there is no floor
int curr_station; // tells us the lift pos
int prev_station; // where did we come from
int delay_at_floor; // tells us how long to stay at floor
int delay_between_floors; // tells us how long before teleport
LIFT_MOTION motion;
LIFT_CTRL_STATES state;
BOOL floor_switches_fixed;
int SoundHandle;
} LIFT_CONTROL_BLOCK;
typedef struct lift_behaviour
{
AVP_BEHAVIOUR_TYPE bhvr_type;
char control_sb_name[SB_NAME_LENGTH];
STRATEGYBLOCK* control_sb;
LIFT_CONTROL_BLOCK* lift_control;
LIFT_STATION lift_station;
int controller;
} LIFT_BEHAV_BLOCK;
#define LiftFlag_Here 0x00000001
#define LiftFlag_Airlock 0x00000002
#define LiftFlag_NoTel 0x00000004 /*switches aren't teleported*/
typedef struct lift_tools_template
{
// for behaviour block
char control_sb_name[SB_NAME_LENGTH];
int controller;
// for control block
int num_stations;
// for station block
char call_switch_name[SB_NAME_LENGTH];
char lift_door_name[SB_NAME_LENGTH];
char lift_floor_switch_name[SB_NAME_LENGTH];
char my_module_name[SB_NAME_LENGTH];
int environment;
int num_floor;
int lift_flags;
int orient;
// for strategy block
MREF my_module;
char nameID[SB_NAME_LENGTH];
} LIFT_TOOLS_TEMPLATE;
extern int RequestEnvChangeViaLift;
extern int RequestEnvChangeViaAirlock;

1150
src/avp/bh_light.c Normal file

File diff suppressed because it is too large Load diff

141
src/avp/bh_light.h Normal file
View file

@ -0,0 +1,141 @@
typedef enum light_state
{
Light_State_Standard,
Light_State_Broken,
Light_State_StrobeUp,
Light_State_StrobeDown,
Light_State_StrobeUpDelay,
Light_State_StrobeDownDelay,
Light_State_Flicker,
}LIGHT_STATE;
typedef enum light_on_off_state
{
Light_OnOff_Off,
Light_OnOff_On,
Light_OnOff_FadeOff,
Light_OnOff_FadeOn,
Light_OnOff_Flicker,
}LIGHT_ON_OFF_STATE;
typedef enum light_type
{
Light_Type_Standard,
Light_Type_Strobe,
Light_Type_Flicker,
}LIGHT_TYPE;
typedef enum light_on_off_type
{
Light_OnOff_Type_Standard,
Light_OnOff_Type_Fade,
Light_OnOff_Type_Flicker,
}LIGHT_ON_OFF_TYPE;
typedef struct placed_light_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
BOOL Indestructable;
TXACTRLBLK *inan_tac;//for lights with anims on them
LIGHTBLOCK* light;
LIGHT_STATE state;
LIGHT_ON_OFF_STATE on_off_state;
int sequence; //texture animation sequence
int colour_red; //colour for fade up state
int colour_green;
int colour_blue;
int colour_diff_red; //difference from up colour to down colour
int colour_diff_green;
int colour_diff_blue;
int fade_up_time;
int fade_down_time;
int up_time;
int down_time;
int timer;
int on_off_timer;
int flicker_timer;
LIGHT_TYPE type;
LIGHT_ON_OFF_TYPE on_off_type;
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* destruct_target_sbptr;
VECTORCH corona_location;
int startingHealth; //for network games
int startingArmour;
int has_broken_sequence:1; //is there a third texture sequence
int has_corona:1;
int swap_colour_and_brightness_alterations:1;
}PLACED_LIGHT_BEHAV_BLOCK;
typedef struct toolsdata_placed_light
{
struct vectorch position;
struct euler orientation;
int shapeIndex; /* for john */
char nameID[SB_NAME_LENGTH];
int mass; // Kilos??
int integrity; // 0-20 (>20 = indestructable)
LIGHTBLOCK* light;
unsigned int static_light:1;
int sequence;
int colour_red;
int colour_green;
int colour_blue;
int colour_diff_red;
int colour_diff_green;
int colour_diff_blue;
int fade_up_time;
int fade_down_time;
int up_time;
int down_time;
int timer;
LIGHT_STATE state;
LIGHT_ON_OFF_STATE on_off_state;
LIGHT_TYPE type;
LIGHT_ON_OFF_TYPE on_off_type;
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
int swap_colour_and_brightness_alterations:1;
}TOOLS_DATA_PLACEDLIGHT;
void* InitPlacedLight(void* bhdata,STRATEGYBLOCK *sbPtr);
void PlacedLightBehaviour(STRATEGYBLOCK *sbPtr);
void MakePlacedLightNear(STRATEGYBLOCK *sbPtr);
void PlacedLightIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple);
void SendRequestToPlacedLight(STRATEGYBLOCK* sbptr,BOOL state,int extended_data);
void RespawnLight(STRATEGYBLOCK *sbPtr);
void KillLightForRespawn(STRATEGYBLOCK *sbPtr);

863
src/avp/bh_lnksw.c Normal file
View file

@ -0,0 +1,863 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_lnksw.h"
#include "dynblock.h"
#include "dynamics.h"
#include "pldghost.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pmove.h"
#include "pvisible.h"
#include "bh_binsw.h"
#include "plat_shp.h"
#include "psnd.h"
#include "inventry.h"
extern int NormalFrameTime;
extern int RealFrameTime;
static BOOL check_link_switch_states (LINK_SWITCH_BEHAV_BLOCK * lsbb)
{
int i=0;
LSWITCH_ITEM * lsi = lsbb->lswitch_list;
// textprint ("Checking link states\n");
if (!lsbb->state)
return(No);
// textprint ("Link switch OK\n");
while (i < lsbb->num_linked_switches)
{
if(lsi[i].bswitch->I_SBtype==I_BehaviourBinarySwitch)
{
BINARY_SWITCH_BEHAV_BLOCK * bsbb = ((BINARY_SWITCH_BEHAV_BLOCK *)lsi[i].bswitch->SBdataptr);
// if it's off return No
if (!bsbb->state)
return(No);
// textprint ("Switch %d OK\n", i);
}
else if(lsi[i].bswitch->I_SBtype==I_BehaviourLinkSwitch)
{
LINK_SWITCH_BEHAV_BLOCK * linked_lsbb = ((LINK_SWITCH_BEHAV_BLOCK *)lsi[i].bswitch->SBdataptr);
// if the system state is off return No
if (!linked_lsbb->system_state)
return(No);
}
else
{
GLOBALASSERT(0=="Switch should only have links to link switches and binary switches");
}
i++;
}
// textprint ("Link switchs activated\n");
return(Yes);
}
#if 0
static void set_link_switch_states_off (LINK_SWITCH_BEHAV_BLOCK * lsbb)
{
int i=0;
LSWITCH_ITEM * lsi = lsbb->lswitch_list;
while (lsi[i].bswitch && i < MAX_SWITCHES_FOR_LINK)
{
BINARY_SWITCH_BEHAV_BLOCK * bsbb = ((BINARY_SWITCH_BEHAV_BLOCK *)lsi[i].bswitch->SBdataptr);
// if it's on, tell it to go off
if (! ((bsbb->state && bsbb->rest_state) || (!bsbb->state && !bsbb->rest_state)) )
RequestState (lsi->bswitch, 0, 0);
i++;
}
}
#endif
void* LinkSwitchBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
{
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
LINK_SWITCH_TOOLS_TEMPLATE *ls_tt;
int i;
GLOBALASSERT(sbptr);
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)AllocateMem(sizeof(LINK_SWITCH_BEHAV_BLOCK));
if(!ls_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
ls_bhv->bhvr_type = I_BehaviourLinkSwitch;
// from loaders
// 1 rest_state - on or off
// 2 mode
// 3 timer switch - time for reset
// 4 security clerance to operate
// 5 copy the target name
ls_tt = (LINK_SWITCH_TOOLS_TEMPLATE*)bhdata;
sbptr->shapeIndex = ls_tt->shape_num;
COPY_NAME(sbptr->SBname, ls_tt->nameID);
if (ls_tt->mode == I_lswitch_SELFDESTRUCT)
{
ls_bhv->ls_mode = I_lswitch_timer;
ls_bhv->IS_SELF_DESTRUCT = Yes;
}
else
{
ls_bhv->ls_mode = ls_tt->mode;
ls_bhv->IS_SELF_DESTRUCT = No;
}
ls_bhv->num_targets=ls_tt->num_targets;
if(ls_bhv->num_targets)
{
ls_bhv->ls_targets = (LINK_SWITCH_TARGET*)AllocateMem(sizeof(LINK_SWITCH_TARGET) * ls_tt->num_targets);
if (!ls_bhv->ls_targets)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
}
else
{
ls_bhv->ls_targets=0;
}
for (i=0; i<ls_tt->num_targets; i++)
{
ls_bhv->ls_targets[i]=ls_tt->targets[i];
ls_bhv->ls_targets[i].sbptr = 0;
}
ls_bhv->time_for_reset = ls_tt->time_for_reset;
ls_bhv->security_clerance = ls_tt->security_clearance;
ls_bhv->switch_flags=ls_tt->switch_flags;
ls_bhv->trigger_volume_min=ls_tt->trigger_volume_min;
ls_bhv->trigger_volume_max=ls_tt->trigger_volume_max;
ls_bhv->switch_always_on = ls_tt->switch_always_on;
ls_bhv->switch_off_message_same=ls_tt->switch_off_message_same;
ls_bhv->switch_off_message_none=ls_tt->switch_off_message_none;
if(sbptr->DynPtr) //there may be no shape
{
sbptr->DynPtr->Position = sbptr->DynPtr->PrevPosition = ls_tt->position;
sbptr->DynPtr->OrientEuler = ls_tt->orientation;
CreateEulerMatrix(&sbptr->DynPtr->OrientEuler, &sbptr->DynPtr->OrientMat);
TransposeMatrixCH(&sbptr->DynPtr->OrientMat);
}
// set up the animation control
if(sbptr->shapeIndex!=-1)
{
int item_num;
TXACTRLBLK **pptxactrlblk;
int shape_num = ls_tt->shape_num;
SHAPEHEADER *shptr = GetShapeData(shape_num);
SetupPolygonFlagAccessForShape(shptr);
pptxactrlblk = &ls_bhv->ls_tac;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
int num_seq = 0;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if (pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = ls_tt->rest_state;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num);
while(pnew_txactrlblk->tac_txarray[num_seq+1])num_seq++;
// Assert does not work at this point so
GLOBALASSERT(num_seq==2);
/* set the flags in the animation header */
// we only ever have one frame of animation per sequence -
// nb this can change talk to richard - one sequence with two frames
// or mutliple sequences???
//Now two sequences with an arbitrary number of frames - Richard
pnew_txactrlblk->tac_txah.txa_flags |= txa_flag_play;
/* change the value held in pptxactrlblk
which point to the previous structures "next"
pointer*/
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else
{
memoryInitialisationFailure = 1;
}
}
}
*pptxactrlblk=0;
}
else
{
//no shape - so there won't be any animation
ls_bhv->ls_tac=0;
}
ls_bhv->ls_dtype = linkswitch_no_display;
if (ls_bhv->ls_tac)
{
ls_bhv->ls_dtype = linkswitch_animate_me;
}
ls_bhv->ls_track=ls_tt->track;
if (ls_bhv->ls_track)
{
ls_bhv->ls_track->sbptr=sbptr;
if (ls_bhv->ls_dtype == linkswitch_animate_me)
{
ls_bhv->ls_dtype = linkswitch_animate_and_move_me;
}
else
{
ls_bhv->ls_dtype = linkswitch_move_me;
}
}
// fill in the rest ourselves
ls_bhv->request = 0;
ls_bhv->state = ls_tt->rest_state;
ls_bhv->timer = 0;
ls_bhv->system_state = 0;
ls_bhv->soundHandle = SOUND_NOACTIVEINDEX;
ls_bhv->num_linked_switches=ls_tt->num_linked_switches;
if(ls_tt->num_linked_switches)
ls_bhv->lswitch_list=(LSWITCH_ITEM*)AllocateMem(sizeof(LSWITCH_ITEM)*ls_bhv->num_linked_switches);
else
ls_bhv->lswitch_list=0;
for (i=0; i<ls_tt->num_linked_switches; i++)
{
COPY_NAME (ls_bhv->lswitch_list[i].bs_name, ls_tt->switchIDs[i].name);
}
if(ls_bhv->state)
{
ls_bhv->timer=ls_bhv->time_for_reset;
if(ls_bhv->ls_track)
{
//set the track to the end position
ls_bhv->ls_track->current_section=(ls_bhv->ls_track->num_sections-1);
ls_bhv->ls_track->timer=ls_bhv->ls_track->sections[ls_bhv->ls_track->current_section].time_for_section;
ls_bhv->ls_track->playing=1;
Update_Track_Position(ls_bhv->ls_track);
}
}
ls_bhv->TimeUntilNetSynchAllowed=0;
return((void*)ls_bhv);
}
void LinkSwitchBehaveFun(STRATEGYBLOCK* sbptr)
{
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
DISPLAYBLOCK* dptr;
int i;
GLOBALASSERT(sbptr);
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((ls_bhv->bhvr_type == I_BehaviourLinkSwitch));
dptr = sbptr->SBdptr;
// if(AvP.Network!=I_No_Network) return; /* disable for network game */
/******
What I need to do - check to see if we have
a request - requests have different effects depending on
the mode - so we have to switch on the mode
*****/
if (ls_bhv->ls_dtype == linkswitch_animate_me || ls_bhv->ls_dtype == linkswitch_animate_and_move_me)
{
if(dptr)
dptr->ObTxAnimCtrlBlks = ls_bhv->ls_tac;
}
if (!ReturnPlayerSecurityClearance(0,ls_bhv->security_clerance) && ls_bhv->security_clerance)
{
ls_bhv->request = I_no_request;
return;
}
if(ls_bhv->switch_flags && SwitchFlag_UseTriggerVolume)
{
/*See if switch has been set off*/
int i;
for (i=0; i<NumActiveStBlocks; i++)
{
int needToTest = 0;
STRATEGYBLOCK *sbPtr = ActiveStBlockList[i];
if (sbPtr->DynPtr)
{
if (sbPtr->SBdptr == Player)
{
needToTest = 1;
}
else if (sbPtr->I_SBtype == I_BehaviourNetGhost)
{
NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
if ((ghostData->type == I_BehaviourMarinePlayer)
||(ghostData->type == I_BehaviourAlienPlayer)
||(ghostData->type == I_BehaviourPredatorPlayer))
needToTest = 1;
}
}
if(needToTest&&
sbPtr->DynPtr->Position.vx > ls_bhv->trigger_volume_min.vx &&
sbPtr->DynPtr->Position.vx < ls_bhv->trigger_volume_max.vx &&
sbPtr->DynPtr->Position.vy > ls_bhv->trigger_volume_min.vy &&
sbPtr->DynPtr->Position.vy < ls_bhv->trigger_volume_max.vy &&
sbPtr->DynPtr->Position.vz > ls_bhv->trigger_volume_min.vz &&
sbPtr->DynPtr->Position.vz < ls_bhv->trigger_volume_max.vz)
{
ls_bhv->request=I_request_on;
break;
}
}
}
if (ls_bhv->request == I_request_on)
{
if (ls_bhv->triggered_last)
{
ls_bhv->request = I_no_request;
}
else
{
ls_bhv->triggered_last = Yes;
}
}
else
{
ls_bhv->triggered_last = No;
}
if(ls_bhv->switch_always_on)
{
ls_bhv->request=I_no_request;
ls_bhv->state=1;
}
if(AvP.Network != I_No_Network)
{
/*
Every time a switch is updated there is a time delay of 5 seconds before the
switch can next be changed by the host sending synch messages.
This prevents the host machine from resetting a switch before it learns that
it has been pressed
*/
if(ls_bhv->request == I_no_request)
{
ls_bhv->TimeUntilNetSynchAllowed-=RealFrameTime;
if(ls_bhv->TimeUntilNetSynchAllowed<0)
{
ls_bhv->TimeUntilNetSynchAllowed=0;
}
}
else
{
ls_bhv->TimeUntilNetSynchAllowed=5*ONE_FIXED;
}
}
switch(ls_bhv->ls_mode)
{
case I_lswitch_timer:
{
if(ls_bhv->request == I_request_on && !ls_bhv->state)
{
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if(!ls_bhv->ls_track || !ls_bhv->ls_track->sound)
{
if (ls_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_SWITCH1,"eh",&ls_bhv->soundHandle);
}
}
}
ls_bhv->timer = ls_bhv->time_for_reset;
if (ls_bhv->ls_dtype == binswitch_move_me || ls_bhv->ls_dtype == binswitch_animate_and_move_me)
{
// moving switch
ls_bhv->new_state = 1;
ls_bhv->new_request = -1;
ls_bhv->ls_track->reverse=0;
Start_Track_Playing(ls_bhv->ls_track);
ls_bhv->mode_store = ls_bhv->ls_mode;
ls_bhv->ls_mode = I_lswitch_moving;
}
else
{
ls_bhv->state = 1;
}
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = 1;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbptr->shapeIndex));
}
}
else if(ls_bhv->timer > 0)
{
ls_bhv->timer -= NormalFrameTime;
if(ls_bhv->timer <= 0)
{
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if(!ls_bhv->ls_track || !ls_bhv->ls_track->sound)
{
if (ls_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_SWITCH2,"eh",&ls_bhv->soundHandle);
}
}
}
ls_bhv->state = 0;
if (ls_bhv->ls_dtype == binswitch_move_me || ls_bhv->ls_dtype == binswitch_animate_and_move_me)
{
// moving switch
ls_bhv->new_state = 0;
ls_bhv->new_request = -1;
ls_bhv->ls_track->reverse=1;
Start_Track_Playing(ls_bhv->ls_track);
ls_bhv->mode_store = ls_bhv->ls_mode;
ls_bhv->ls_mode = I_lswitch_moving;
}
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = 0;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbptr->shapeIndex));
}
}
}
break;
}
case I_lswitch_toggle:
{
// if it's off and no request then we can return
if (!ls_bhv->state)
if(ls_bhv->request == I_no_request)
return;
/* change the state and request the new state in
the target */
if(ls_bhv->request != I_no_request)
{
if(ls_bhv->ls_dtype == binswitch_move_me || ls_bhv->ls_dtype == binswitch_animate_and_move_me)
{
// moving switch
ls_bhv->new_state = !ls_bhv->state;
ls_bhv->new_request = -1;
ls_bhv->mode_store = ls_bhv->ls_mode;
ls_bhv->ls_mode = I_lswitch_moving;
ls_bhv->ls_track->reverse=ls_bhv->state;
Start_Track_Playing(ls_bhv->ls_track);
}
else
{
ls_bhv->state = !ls_bhv->state;
}
if(sbptr->shapeIndex!=-1)//don't play a sound if there is no shape
{
if(!ls_bhv->ls_track || !ls_bhv->ls_track->sound)
{
if (ls_bhv->soundHandle == SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_SWITCH1,"eh",&ls_bhv->soundHandle);
}
}
}
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = ls_bhv->state ? 1 : 0;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbptr->shapeIndex));
}
}
break;
}
case I_lswitch_wait:
{
// if it's off and no request then we can return
if (!ls_bhv->state)
if(ls_bhv->request == I_no_request)
return;
if(ls_bhv->request == I_request_on)
{
if(!ls_bhv->state)//can only be switched on if currently off
{
if(!ls_bhv->ls_track || !ls_bhv->ls_track->sound)
{
Sound_Play(SID_SWITCH2,"eh",&ls_bhv->soundHandle);
}
if(ls_bhv->ls_dtype == binswitch_move_me || ls_bhv->ls_dtype == binswitch_animate_and_move_me)
{
// moving switch
ls_bhv->new_state = 1;
ls_bhv->new_request = -1;
ls_bhv->ls_track->reverse=0;
Start_Track_Playing(ls_bhv->ls_track);
ls_bhv->mode_store = ls_bhv->ls_mode;
ls_bhv->ls_mode = I_lswitch_moving;
}
else
{
ls_bhv->state = 1;
}
}
}
else if (ls_bhv->request == I_request_off)
{
if(ls_bhv->state)//can only be switched off if currently on
{
if(!ls_bhv->ls_track || !ls_bhv->ls_track->sound)
{
Sound_Play(SID_SWITCH1,"eh",&ls_bhv->soundHandle);
}
if(ls_bhv->ls_dtype == binswitch_move_me || ls_bhv->ls_dtype == binswitch_animate_and_move_me)
{
// moving switch
ls_bhv->new_state = 0;
ls_bhv->new_request = -1;
ls_bhv->ls_track->reverse=1;
Start_Track_Playing(ls_bhv->ls_track);
ls_bhv->mode_store = ls_bhv->ls_mode;
ls_bhv->ls_mode = I_lswitch_moving;
}
else
{
ls_bhv->state = 0;
}
}
}
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = ls_bhv->state ? 1 : 0;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbptr->shapeIndex));
}
break;
}
case I_lswitch_moving:
{
textprint ("moving\n");
Update_Track_Position(ls_bhv->ls_track);
if (!ls_bhv->ls_track->playing)
{
ls_bhv->ls_mode = ls_bhv->mode_store;
ls_bhv->state = ls_bhv->new_state;
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = ls_bhv->state ? 1 : 0;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbptr->shapeIndex));
}
}
}
break;
default:
GLOBALASSERT(2<1);
}
ls_bhv->request = I_no_request;
//check to see if the system state has changed
if (ls_bhv->system_state)
{
if (!check_link_switch_states(ls_bhv))
{
ls_bhv->system_state = No;
//link switch system state is turning off
if(!ls_bhv->switch_off_message_none)
{
for(i=0;i<ls_bhv->num_targets;i++)
{
RequestState(ls_bhv->ls_targets[i].sbptr,ls_bhv->ls_targets[i].request_message^(!ls_bhv->switch_off_message_same), sbptr);
}
}
}
}
else
{
if (check_link_switch_states(ls_bhv))
{
ls_bhv->system_state = Yes;
//link switch system state is turning on
for(i=0;i<ls_bhv->num_targets;i++)
{
RequestState(ls_bhv->ls_targets[i].sbptr,ls_bhv->ls_targets[i].request_message, sbptr);
}
}
}
}
#define LINKSWITCHSYNCH_ON 0
#define LINKSWITCHSYNCH_OFF 1
#define LINKSWITCHSYNCH_IGNORE 2
int LinkSwitchGetSynchData(STRATEGYBLOCK* sbPtr)
{
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
GLOBALASSERT(sbPtr);
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GLOBALASSERT((ls_bhv->bhvr_type == I_BehaviourLinkSwitch));
//don't try to synch moving switches
if(ls_bhv->ls_mode==I_lswitch_moving)
{
return LINKSWITCHSYNCH_IGNORE;
}
if(ls_bhv->state)
return LINKSWITCHSYNCH_ON;
else
return LINKSWITCHSYNCH_OFF;
}
void LinkSwitchSetSynchData(STRATEGYBLOCK* sbPtr,int status)
{
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
GLOBALASSERT(sbPtr);
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GLOBALASSERT((ls_bhv->bhvr_type == I_BehaviourLinkSwitch));
if(ls_bhv->TimeUntilNetSynchAllowed>0)
{
//ignore this attempt to synch the switch
return;
}
//don't try to synch moving switches
if(ls_bhv->ls_mode==I_lswitch_moving)
{
return;
}
switch(status)
{
case LINKSWITCHSYNCH_ON :
if(!ls_bhv->state)
{
//this switch should be on
RequestState(sbPtr,1,0);
}
break;
case LINKSWITCHSYNCH_OFF :
if(ls_bhv->state)
{
//this switch should be off
RequestState(sbPtr,0,0);
}
break;
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct link_switch_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BINARY_SWITCH_REQUEST_STATE request;
BOOL system_state;
BOOL state;
LSWITCH_MODE ls_mode;
int timer;
BOOL new_state;
int new_request;
LSWITCH_MODE mode_store;
BOOL triggered_last;
int txanim_sequence;
}LINK_SWITCH_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV ls_bhv
void LoadStrategy_LinkSwitch(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
LINK_SWITCH_SAVE_BLOCK* block = (LINK_SWITCH_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourLinkSwitch) return;
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(request)
COPYELEMENT_LOAD(system_state)
COPYELEMENT_LOAD(state)
COPYELEMENT_LOAD(ls_mode)
COPYELEMENT_LOAD(timer)
COPYELEMENT_LOAD(new_state)
COPYELEMENT_LOAD(new_request)
COPYELEMENT_LOAD(mode_store)
COPYELEMENT_LOAD(triggered_last)
//set the texture animation sequence
if(ls_bhv->ls_tac)
{
ls_bhv->ls_tac->tac_sequence = block->txanim_sequence;
ls_bhv->ls_tac->tac_txah_s = GetTxAnimHeaderFromShape(ls_bhv->ls_tac, (sbPtr->shapeIndex));
}
//load the track position , if the switch has one
if(ls_bhv->ls_track)
{
SAVE_BLOCK_HEADER* track_header = GetNextBlockIfOfType(SaveBlock_Track);
if(track_header)
{
LoadTrackPosition(track_header,ls_bhv->ls_track);
}
}
}
void SaveStrategy_LinkSwitch(STRATEGYBLOCK* sbPtr)
{
LINK_SWITCH_SAVE_BLOCK *block;
LINK_SWITCH_BEHAV_BLOCK *ls_bhv;
ls_bhv = (LINK_SWITCH_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(request)
COPYELEMENT_SAVE(system_state)
COPYELEMENT_SAVE(state)
COPYELEMENT_SAVE(ls_mode)
COPYELEMENT_SAVE(timer)
COPYELEMENT_SAVE(new_state)
COPYELEMENT_SAVE(new_request)
COPYELEMENT_SAVE(mode_store)
COPYELEMENT_SAVE(triggered_last)
//get the animation sequence
if(ls_bhv->ls_tac)
{
block->txanim_sequence = ls_bhv->ls_tac->tac_sequence;
}
else
{
block->txanim_sequence = 0;
}
//save the track position , if the switch has one
if(ls_bhv->ls_track)
{
SaveTrackPosition(ls_bhv->ls_track);
}
}

163
src/avp/bh_lnksw.h Normal file
View file

@ -0,0 +1,163 @@
#ifndef _bhlnksw_h_
#define _bhlnksw_h_ 1
#include "track.h"
#ifdef __cplusplus
extern "C" {
#endif
void* LinkSwitchBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
void LinkSwitchBehaveFun(STRATEGYBLOCK* sbptr);
extern int LinkSwitchGetSynchData(STRATEGYBLOCK* sbptr);
extern void LinkSwitchSetSynchData(STRATEGYBLOCK* sbptr,int status);
typedef enum link_switch_mode
{
I_lswitch_timer,
I_lswitch_wait,
I_lswitch_toggle,
I_lswitch_moving,
I_lswitch_SELFDESTRUCT,
} LSWITCH_MODE;
typedef enum link_switch_req_states
{
linkswitch_no_request,
linkswitch_request_on,
linkswitch_request_off,
}LINK_SWITCH_REQUEST_STATE;
typedef enum lswitch_display_types
{
linkswitch_no_display,
linkswitch_animate_me,
linkswitch_move_me,
linkswitch_animate_and_move_me,
} LSWITCH_DISPLAY_TYPES;
typedef enum ls_move_dir
{
ls_start_to_end,
ls_end_to_start,
} LS_MOVE_DIR;
typedef struct lswitch_item
{
STRATEGYBLOCK * bswitch;
char bs_name [SB_NAME_LENGTH];
} LSWITCH_ITEM;
typedef struct link_switch_target
{
char name[SB_NAME_LENGTH];
int request_message;
STRATEGYBLOCK* sbptr;
}LINK_SWITCH_TARGET;
typedef struct link_switch
{
AVP_BEHAVIOUR_TYPE bhvr_type;
LINK_SWITCH_REQUEST_STATE request;
BOOL system_state;
BOOL state;
LSWITCH_MODE ls_mode;
int num_targets;
LINK_SWITCH_TARGET* ls_targets;
int time_for_reset; // constant
int timer;
int security_clerance; // what the plyer has to be to use this switch
int num_linked_switches;
LSWITCH_ITEM* lswitch_list ;
// stuff for showing how the switch displays its state
LSWITCH_DISPLAY_TYPES ls_dtype;
TXACTRLBLK *ls_tac; // animations
// or track
TRACK_CONTROLLER* ls_track;
BOOL new_state;
int new_request;
LSWITCH_MODE mode_store;
// SELF DESTRUCT SEQUENCE STUFF
BOOL IS_SELF_DESTRUCT;
int soundHandle;
BOOL triggered_last;
int switch_flags;
VECTORCH trigger_volume_min;//for switches that can be set off by walking
VECTORCH trigger_volume_max;//into a given area
unsigned int switch_always_on:1;
unsigned int switch_off_message_same:1;
unsigned int switch_off_message_none:1;
int TimeUntilNetSynchAllowed;
}LINK_SWITCH_BEHAV_BLOCK;
typedef struct link_switch_tools_template
{
VECTORCH position;
EULER orientation;
BOOL rest_state;
int mode;
int time_for_reset;
int security_clearance;
int num_targets;
LINK_SWITCH_TARGET * targets;
int shape_num;
TRACK_CONTROLLER* track;
char nameID[SB_NAME_LENGTH];
int num_linked_switches;
SBNAMEBLOCK* switchIDs;
int switch_flags;
VECTORCH trigger_volume_min;//for switches that can be set off by walking
VECTORCH trigger_volume_max;//into a given area
unsigned int switch_always_on:1;
unsigned int switch_off_message_same:1;
unsigned int switch_off_message_none:1;
} LINK_SWITCH_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

643
src/avp/bh_ltfx.c Normal file
View file

@ -0,0 +1,643 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "dynblock.h"
#include "dynamics.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "bh_ltfx.h"
extern int NormalFrameTime;
#if PSX
void * LightFXBehaveInit (void * bhdata, STRATEGYBLOCK* sbptr)
{
}
void LightFXBehaveFun (STRATEGYBLOCK* sbptr)
{
}
#else
void * LightFXBehaveInit (void * bhdata, STRATEGYBLOCK* sbptr)
{
LIGHT_FX_BEHAV_BLOCK * lfxbb;
LIGHT_FX_TOOLS_TEMPLATE * lfxtt;
MODULE * my_mod;
GLOBALASSERT(sbptr);
lfxbb = (LIGHT_FX_BEHAV_BLOCK *)AllocateMem(sizeof(LIGHT_FX_BEHAV_BLOCK));
if (!lfxbb)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
lfxtt = (LIGHT_FX_TOOLS_TEMPLATE *)bhdata;
COPY_NAME (sbptr->SBname, lfxtt->nameID);
lfxbb->bhvr_type = I_BehaviourLightFX;
// Setup module ref
{
MREF mref=lfxtt->my_module;
ConvertModuleNameToPointer (&mref, MainSceneArray[0]->sm_marray);
my_mod = mref.mref_ptr;
}
my_mod->m_sbptr = sbptr;
sbptr->SBmoptr = my_mod;
sbptr->SBmomptr = my_mod->m_mapptr;
sbptr->SBflags.no_displayblock = 1;
GLOBALASSERT (my_mod);
lfxbb->type = lfxtt->light_data.type;
lfxbb->current_state = lfxtt->light_data.init_state;
lfxbb->fade_up_speed = lfxtt->light_data.fade_up_speed;
lfxbb->fade_down_speed = lfxtt->light_data.fade_down_speed;
lfxbb->post_fade_up_delay = lfxtt->light_data.post_fade_up_delay;
lfxbb->post_fade_down_delay = lfxtt->light_data.post_fade_down_delay;
if (lfxbb->fade_up_speed == 0)
lfxbb->fade_up_speed = 10;
if (lfxbb->fade_down_speed == 0)
lfxbb->fade_down_speed = 10;
if (lfxbb->post_fade_up_delay == 0)
lfxbb->post_fade_up_delay = 10;
if (lfxbb->post_fade_down_delay == 0)
lfxbb->post_fade_down_delay = 10;
lfxbb->fade_up_speed_multiplier = DIV_FIXED (ONE_FIXED, lfxbb->fade_up_speed);
lfxbb->fade_down_speed_multiplier = DIV_FIXED (ONE_FIXED, lfxbb->fade_down_speed);
lfxbb->post_fade_up_delay_multiplier = DIV_FIXED (ONE_FIXED, lfxbb->post_fade_up_delay);
lfxbb->post_fade_down_delay_multiplier = DIV_FIXED (ONE_FIXED, lfxbb->post_fade_down_delay);
switch (lfxbb->type)
{
case LFX_Strobe:
case LFX_Switch:
case LFX_FlickySwitch:
{
switch (lfxbb->current_state)
{
case LFXS_LightOn:
{
lfxbb->multiplier = ONE_FIXED;
lfxbb->timer = 0;
lfxbb->timer2 = 0;
break;
}
case LFXS_LightOff:
{
lfxbb->multiplier = 0;
lfxbb->timer = 0;
lfxbb->timer2 = 0;
break;
}
default:
{
lfxbb->multiplier = ONE_FIXED;
lfxbb->timer = 0;
lfxbb->timer2 = 0;
break;
}
}
break;
}
case LFX_RandomFlicker:
{
lfxbb->current_state = LFXS_Flicking;
lfxbb->multiplier = ONE_FIXED;
lfxbb->timer = 0;
lfxbb->timer2 = 0;
lfxbb->time_to_next_flicker_state = 0;
break;
}
default:
{
lfxbb->multiplier = ONE_FIXED;
lfxbb->timer = 0;
lfxbb->timer2 = 0;
lfxbb->time_to_next_flicker_state = 0;
break;
}
}
/* see if this module has a texture animation*/
{
TXACTRLBLK **pptxactrlblk;
int item_num;
int shape_num=sbptr->shapeIndex;
SHAPEHEADER *shptr = GetShapeData(shape_num);
pptxactrlblk = &lfxbb->anim_control;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if (pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = 0;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num);
/* change the value held in pptxactrlblk
which point to the previous structures "next"
pointer*/
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else
{
memoryInitialisationFailure = 1;
}
}
}
*pptxactrlblk=0;
}
return((void*)lfxbb);
}
void LightFXBehaveFun (STRATEGYBLOCK* sbptr)
{
LIGHT_FX_BEHAV_BLOCK * lfxbb;
DISPLAYBLOCK* dptr;
MODULE *mptr;
GLOBALASSERT(sbptr);
mptr = sbptr->SBmoptr;
dptr = sbptr->SBdptr;
lfxbb = (LIGHT_FX_BEHAV_BLOCK *)sbptr->SBdataptr;
GLOBALASSERT((lfxbb->bhvr_type == I_BehaviourLightFX));
/*deal with any texture animation*/
if(lfxbb->anim_control)
{
if(dptr)
{
if(!dptr->ObTxAnimCtrlBlks)
{
dptr->ObTxAnimCtrlBlks = lfxbb->anim_control;
}
}
}
/*now update the lighting effects*/
switch (lfxbb->type)
{
case LFX_RandomFlicker:
{
if (dptr)
{
switch (lfxbb->current_state)
{
case LFXS_Flicking:
{
lfxbb->time_to_next_flicker_state -= NormalFrameTime;
if (lfxbb->time_to_next_flicker_state < 0 && 0)
{
int j;
lfxbb->multiplier = FastRandom() & 65535;
lfxbb->current_state = LFXS_NotFlicking;
lfxbb->time_to_next_flicker_state = ((FastRandom() & 65535));
lfxbb->multiplier &= ~0xf000;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
lfxbb->timer = 0;
}
else
{
lfxbb->timer += NormalFrameTime;
if (lfxbb->timer > 1750)
{
int j;
lfxbb->multiplier = FastRandom() & 65535;
if (!((lfxbb->multiplier % 24 )>>3))
{
lfxbb->multiplier |= 0xa000;
}
else
{
lfxbb->multiplier &= ~0xf000;
}
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
lfxbb->timer = 0;
}
}
break;
}
case LFXS_NotFlicking:
{
lfxbb->time_to_next_flicker_state -= NormalFrameTime;
if (lfxbb->time_to_next_flicker_state < 0)
{
lfxbb->current_state = LFXS_Flicking;
lfxbb->time_to_next_flicker_state = FastRandom() & 65535;
}
break;
}
case LFXS_LightOff :
{
int j;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = 0;
}
}
break;
}
default:
{
break;
}
}
}
break;
}
case LFX_Strobe:
{
switch (lfxbb->current_state)
{
case LFXS_LightOn:
{
lfxbb->timer += MUL_FIXED (NormalFrameTime, lfxbb->post_fade_up_delay_multiplier);
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightFadingDown;
lfxbb->timer = 0;
}
break;
}
case LFXS_LightOff:
{
lfxbb->timer += MUL_FIXED (NormalFrameTime, lfxbb->post_fade_down_delay_multiplier);
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightFadingUp;
lfxbb->timer = 0;
}
break;
}
case LFXS_LightFadingUp:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_up_speed_multiplier);
lfxbb->timer += diff;
lfxbb->multiplier += diff;
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOn;
lfxbb->timer = 0;
lfxbb->multiplier = 65536;
}
break;
}
case LFXS_LightFadingDown:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_down_speed_multiplier);
lfxbb->timer += diff;
lfxbb->multiplier -= diff;
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOff;
lfxbb->timer = 0;
lfxbb->multiplier = 0;
}
break;
}
default:
{
GLOBALASSERT (0 == "Light FX state not supported");
break;
}
}
if (dptr)
{
int j;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
}
break;
}
case LFX_Switch:
{
switch (lfxbb->current_state)
{
case LFXS_LightFadingUp:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_up_speed_multiplier);
lfxbb->timer += diff;
lfxbb->multiplier += diff;
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOn;
lfxbb->timer = 0;
lfxbb->multiplier = 65536;
}
break;
}
case LFXS_LightFadingDown:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_down_speed_multiplier);
lfxbb->timer += diff;
lfxbb->multiplier -= diff;
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOff;
lfxbb->timer = 0;
lfxbb->multiplier = 0;
}
break;
}
case LFXS_LightOn:
case LFXS_LightOff:
{
break;
}
default:
{
GLOBALASSERT (0 == "Light FX state not supported");
break;
}
}
if (dptr)
{
int j;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
}
break;
}
case LFX_FlickySwitch:
{
switch (lfxbb->current_state)
{
case LFXS_LightFadingUp:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_up_speed_multiplier);
lfxbb->timer += diff;
lfxbb->timer2 += NormalFrameTime;
if (lfxbb->timer2 > 3553)
{
lfxbb->multiplier = FastRandom() & 65535;
if (!((lfxbb->multiplier % 24 )>>3))
{
lfxbb->multiplier |= 0xa000;
}
else
{
lfxbb->multiplier &= ~0xf000;
}
lfxbb->timer2 = 0;
}
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOn;
lfxbb->timer = 0;
lfxbb->multiplier = 65536;
}
break;
}
case LFXS_LightFadingDown:
{
int diff = MUL_FIXED (NormalFrameTime, lfxbb->fade_down_speed_multiplier);
lfxbb->timer += diff;
lfxbb->multiplier -= diff;
if (lfxbb->timer > ONE_FIXED)
{
lfxbb->current_state = LFXS_LightOff;
lfxbb->timer = 0;
lfxbb->multiplier = 0;
}
break;
}
case LFXS_LightOn:
case LFXS_LightOff:
{
break;
}
default:
{
GLOBALASSERT (0 == "Light FX state not supported");
break;
}
}
if (dptr)
{
int j;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
}
break;
}
default:
{
GLOBALASSERT (0 == "Light FX type not supported");
break;
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct light_fx_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
LIGHT_FX_STATE current_state;
signed long multiplier;
unsigned long timer;
unsigned long timer2;
signed long time_to_next_flicker_state;
}LIGHT_FX_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV lfxbb
void LoadStrategy_LightFx(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
LIGHT_FX_BEHAV_BLOCK * lfxbb;
LIGHT_FX_SAVE_BLOCK* block = (LIGHT_FX_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourLightFX) return;
lfxbb = (LIGHT_FX_BEHAV_BLOCK *)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(current_state)
COPYELEMENT_LOAD(multiplier)
COPYELEMENT_LOAD(timer)
COPYELEMENT_LOAD(timer2)
COPYELEMENT_LOAD(time_to_next_flicker_state)
//update the brightness of the lights
{
DISPLAYBLOCK* dptr = sbPtr->SBdptr;;
if(dptr)
{
//I'm not sure that we will ever have a displayblock at this point, anyway. hmm.
int j;
for (j=0; j<dptr->ObNumLights; j++)
{
LIGHTBLOCK * lp = dptr->ObLights[j];
if (!(lp->LightFlags & LFlag_PreLitSource))
{
lp->LightBright = MUL_FIXED (lp->LightBrightStore, lfxbb->multiplier);
}
}
}
}
}
void SaveStrategy_LightFx(STRATEGYBLOCK* sbPtr)
{
LIGHT_FX_SAVE_BLOCK *block;
LIGHT_FX_BEHAV_BLOCK * lfxbb;
lfxbb = (LIGHT_FX_BEHAV_BLOCK *)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(current_state)
COPYELEMENT_SAVE(multiplier)
COPYELEMENT_SAVE(timer)
COPYELEMENT_SAVE(timer2)
COPYELEMENT_SAVE(time_to_next_flicker_state)
}
#endif

49
src/avp/bh_ltfx.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef _bh_ltfx_h
#define _bh_ltfx_h 1
#include "ltfx_exp.h"
typedef struct light_fx_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
LIGHT_FX_TYPE type;
LIGHT_FX_STATE current_state;
unsigned long fade_up_speed;
unsigned long fade_down_speed;
unsigned long post_fade_up_delay;
unsigned long post_fade_down_delay;
unsigned long fade_up_speed_multiplier;
unsigned long fade_down_speed_multiplier;
unsigned long post_fade_up_delay_multiplier;
unsigned long post_fade_down_delay_multiplier;
signed long multiplier;
unsigned long timer;
unsigned long timer2;
signed long time_to_next_flicker_state;
TXACTRLBLK *anim_control;
} LIGHT_FX_BEHAV_BLOCK;
typedef struct light_fx_tools_template
{
LightFXData light_data;
char nameID[SB_NAME_LENGTH];
MREF my_module;
} LIGHT_FX_TOOLS_TEMPLATE;
void * LightFXBehaveInit (void * bhdata, STRATEGYBLOCK* sbptr);
void LightFXBehaveFun (STRATEGYBLOCK* sbptr);
#endif

19113
src/avp/bh_marin.c Normal file

File diff suppressed because it is too large Load diff

412
src/avp/bh_marin.h Normal file
View file

@ -0,0 +1,412 @@
/*--------------Patrick 14/2/97----------------
Header file for marine support functions
---------------------------------------------*/
#ifndef _bhmarin_h_
#define _bhmarin_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_pred.h"
#include "psndproj.h"
#include "sfx.h"
/*--------------------------------------------
enums of marine far and near behaviour states
--------------------------------------------*/
typedef enum marine_bhstate
{
MBS_Waiting,
/* Waiting - stand and do nothing,
until you get a call, see an enemy,
or begin to fidget. */
MBS_Wandering,
/* Go from module to module around the environment. */
MBS_Retreating,
MBS_Sentry,
MBS_Approaching,
MBS_Firing,
MBS_Avoidance,
MBS_Dying,
MBS_Responding,
MBS_Returning,
MBS_Pathfinding,
MBS_Taunting,
MBS_PanicFire,
MBS_Reloading,
MBS_PumpAction,
MBS_GetWeapon,
MBS_PanicReloading,
MBS_AcidAvoidance,
} MARINE_BHSTATE;
typedef enum marine_movement_style {
MMS_Stationary=0,
MMS_Bored,
MMS_Alert,
MMS_Combat,
MMS_Sprint,
} MARINE_MOVEMENT_STYLE;
typedef enum state_return_condition {
SRC_No_Change,
SRC_Request_Approach,
SRC_Request_Fire,
SRC_Request_Wander,
SRC_Request_Avoidance,
SRC_Request_Wait,
SRC_Request_Retreat,
SRC_Request_Respond,
SRC_Request_Return,
SRC_Request_Taunt,
SRC_Request_PanicFire,
SRC_Request_Reload,
SRC_Request_PumpAction,
SRC_Request_PullPistol,
SRC_Request_PanicReload,
} STATE_RETURN_CONDITION;
/*--------------------------------------------
Enum of marine animation sequences
--------------------------------------------*/
typedef enum MarineSequence
{
MSQ_Walk,
MSQ_StandDieFront,
MSQ_StandDieBack,
MSQ_StartStandingFire,
MSQ_StandingFire,
MSQ_StandDeadFront,
MSQ_StandDeadBack,
MSQ_Crawl,
MSQ_CrouchDie,
MSQ_CrouchDead,
MSQ_RunningFire,
MSQ_Crouch,
MSQ_Stand,
MSQ_Jump,
MSQ_Taunt,
MSQ_Walk_Backwards,
MSQ_Crawl_Backwards,
MSQ_RunningFire_Backwards,
MSQ_StandingFireSecondary,
MSQ_RunningFireSecondary,
MSQ_RunningFireSecondary_Backwards,
MSQ_BaseOfCudgelAttacks=40,
}MARINE_SEQUENCE;
typedef enum MarineMissions {
MM_Wait_Then_Wander, // Should do nothing until visible.
MM_Wander,
MM_Guard,
MM_LocalGuard,
MM_NonCom,
MM_Pathfinder,
MM_RunAroundOnFire,
}MARINE_MISSION;
/***** Marine squad command state *****/
typedef struct squadcommand {
int alertStatus;
int responseLevel;
AIMODULE *alertZone;
int alertPriority;
int Squad_Suspicion;
VECTORCH squad_suspect_point;
/* Now some stats. */
int RespondingMarines;
int Alt_RespondingMarines;
int NearUnpanickedMarines;
int Alt_NearUnpanickedMarines;
int NearPanickedMarines;
int Alt_NearPanickedMarines;
int NearBurningMarines;
int Alt_NearBurningMarines;
int Squad_Delta_Morale;
int Nextframe_Squad_Delta_Morale;
} SQUAD_COMMAND_STATE;
/*--------------------------------------------
Data for civilian accoutement stuff
--------------------------------------------*/
struct hierarchy_shape_replacement;
typedef struct hierarchy_variant_data
{
struct hierarchy_shape_replacement * replacements;
int voice;
unsigned int female :1;
} HIERARCHY_VARIANT_DATA;
/*--------------------------------------------
Marine behaviour data block
--------------------------------------------*/
typedef struct marineStatusBlock
{
signed int health;
signed int volleySize;
signed int primaryWeaponDamage;
MARINE_BHSTATE behaviourState;
MARINE_BHSTATE lastState;
STRATEGYBLOCK *Target;
MARINE_MISSION Mission;
char Target_SBname[SB_NAME_LENGTH];
char death_target_ID[SB_NAME_LENGTH]; //another strategy can be notified of the marine's death
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
STRATEGYBLOCK* generator_sbptr;//0 unless created by a generator
AIMODULE *lastmodule;
AIMODULE *destinationmodule;
AIMODULE *missionmodule;
AIMODULE *fearmodule;
VECTORCH my_spot;
VECTORCH my_facing_point;
/* Movement data. */
signed int nearSpeed;
int acceleration;
int speedConstant;
int accelerationConstant;
/* Sense data */
int mtracker_timer;
VECTORCH suspect_point;
int suspicious;
int previous_suspicion;
int using_squad_suspicion;
int sawlastframe;
int gotapoint;
int lastframe_fallingspeed;
/* Pathfinder parameters */
int path;
int stepnumber;
/* Pathfinder parameters */
int stateTimer;
int internalState;
HMODELCONTROLLER HModelController;
VECTORCH weaponTarget; /* position for firing weapon at */
DISPLAYBLOCK *myGunFlash;
int soundHandle;
int soundHandle2;
NPC_OBSTRUCTIONREPORT obstruction;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
int IAmCrouched;
/* CDF 15/12/97 */
struct marine_weapon_data *My_Weapon;
SECTION_DATA *My_Gunflash_Section;
SECTION_DATA *My_Elevation_Section; /* For elevation computation. */
int lastroundhit;
SECTION_DATA *lasthitsection;
int GibbFactor;
int Wounds;
int incidentFlag;
int incidentTimer;
int weapon_variable;
int weapon_variable2;
int clipammo;
int roundsForThisTarget;
int Female;
int Android;
int Skill;
int Courage;
int Voice;
int VoicePitch;
int FiringAnim;
int Expression;
int Target_Expression;
int Blink;
int SpotFlag;
NPC_AVOIDANCEMANAGER avoidanceManager;
WAYPOINT_MANAGER waypointManager;
}MARINE_STATUS_BLOCK;
typedef enum marine_npc_weapons {
MNPCW_PulseRifle,
MNPCW_Flamethrower,
MNPCW_Smartgun,
MNPCW_SADAR,
MNPCW_GrenadeLauncher,
MNPCW_Minigun,
MNPCW_MShotgun,
MNPCW_MPistol,
MNPCW_MFlamer,
MNPCW_MUnarmed,
MNPCW_MMolotov,
MNPCW_PistolMarine,
MNPCW_Android,
MNPCW_AndroidSpecial,
MNPCW_Android_Pistol_Special,
MNPCW_Scientist_A,
MNPCW_Scientist_B,
MNPCW_TwoPistols,
MNPCW_Skeeter,
MNPCW_End,
} MARINE_NPC_WEAPONS;
/*--------------------------------------------
Tools data template
--------------------------------------------*/
typedef struct tools_data_marine
{
struct vectorch position;
struct vectorch facing_point;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
MARINE_MISSION Mission;
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
enum marine_npc_weapons marine_type;
int path;
int stepnumber;
int textureID;
}TOOLS_DATA_MARINE;
/*--------------------------------------------
Weapon Behaviour Type.
--------------------------------------------*/
typedef struct marine_weapon_data {
MARINE_NPC_WEAPONS id;
enum SFX_ID SfxID;
STATE_RETURN_CONDITION (*WeaponFireFunction)(STRATEGYBLOCK *);
void (*WeaponMisfireFunction)(SECTION_DATA *, int *);
STATE_RETURN_CONDITION (*WeaponPanicFireFunction)(STRATEGYBLOCK *);
char *Riffname;
char *HierarchyName;
char *GunflashName;
char *ElevationSection;
char *HitLocationTableName;
char *TemplateName;
char *ClipName;
int MinRange;
int ForceFireRange;
int MaxRange;
int Accuracy;
int FiringRate;
int FiringTime;
int MinimumBurstSize;
enum AMMO_ID Ammo_Type;
int clip_size;
int Reload_Sequence;
int TargetCallibrationShift;
SOUNDINDEX StartSound;
SOUNDINDEX LoopSound;
SOUNDINDEX EndSound;
unsigned int EnableGrenades :1;
unsigned int UseElevation :1;
unsigned int EnableTracker :1;
unsigned int ARealMarine :1;
unsigned int Android :1;
}MARINE_WEAPON_DATA;
/*--------------------------------------------
Some defines....
--------------------------------------------*/
#define MARINE_STATE_PRINT 0
#define MARINE_STARTING_HEALTH 30
#define NO_OF_FRAGMENTS_FROM_DEAD_MARINE 10
// #define MARINE_NEAR_SPEED 6000 /* mm/s */
/* Experiment. Can they take the ramps? */
#define MARINE_NEAR_SPEED 6000 /* mm/s */
#define MARINE_NEAR_VIEW_WIDTH 500 /* mm */
#define MARINE_WEAPON_DAMAGE 5
#define MARINE_CLOSE_APPROACH_DISTANCE 3000 /* mm */
#define MARINE_FIRINGPOINT_INFRONT 3000 /* 900 mm */
#define MARINE_FIRINGPOINT_ACROSS 300 /* 300 mm */
#define MARINE_FIRINGPOINT_UP 200 /* 200 mm */
#define MARINE_FIRINGPOINT_INFRONT_CROUCHED 900 /* mm */
#define MARINE_FIRINGPOINT_ACROSS_CROUCHED 200 /* mm */
#define MARINE_FIRINGPOINT_UP_CROUCHED 100 /* mm */
#define MARINE_WEAPON_VOLLEYSIZE (1+(FastRandom()&0x02)) /* 1,2 or 3 1/4 second bursts */
#define MARINE_CHANCEOFGRENADE (3)
#define MARINE_TOO_CLOSE_TO_GRENADE_FOOL 3000
#define MARINE_PARANOIA_TIME (ONE_FIXED*10)
#define MARINE_PANIC_TIME (ONE_FIXED*120)
#define SQUAD_PARANOIA_TIME (ONE_FIXED)
/* 1.5-2 seconds in 1/16 second. NB DO NOT INCREASE THIS */
#define MARINE_FAR_MOVE_TIME ((24+(FastRandom()&0x07))*(ONE_FIXED>>4))
/* 1-2 seconds in 1/8ths of a second */
#define MARINE_NEAR_TIMEBETWEENFIRING ((8+(FastRandom()&0x07))*(ONE_FIXED>>3))
// #define MARINE_NEAR_FIRE_TIME (ONE_FIXED>>2) /* 1/4 second */
#define MARINE_NEAR_FIRE_TIME (ONE_FIXED) /* 1 second */
/* random time between 1 and 2 seconds,in fixed point,with granularity 1/8th second */
#define MARINE_NEARWAITTIME (ONE_FIXED+((FastRandom()&0x7)*(ONE_FIXED>>3)))
#define SEAL_NEAR_SPEED 7000
#define SEAL_WEAPON_DAMAGE 15
#define SEAL_STARTING_HEALTH 150
//#define MINIGUN_IDLE_SPEED (ONE_FIXED>>2)
#define MINIGUN_IDLE_SPEED (0)
#define MINIGUN_MAX_SPEED (ONE_FIXED*20)
#define MINIGUN_MINIMUM_BURST (25)
/*--------------------------------------------
Some prototypes...
--------------------------------------------*/
void InitMarineBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void InitSealBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void SendRequestToMarine(STRATEGYBLOCK* sbPtr,BOOL state,int extended_data);
void MarineBehaviour(STRATEGYBLOCK *sbPtr);
void MakeMarineNear(STRATEGYBLOCK *sbPtr);
void MakeMarineFar(STRATEGYBLOCK *sbPtr);
void MarineIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section, VECTORCH *incoming);
void WarnMarineOfAttack(STRATEGYBLOCK *marine,STRATEGYBLOCK *attacker);
DISPLAYBLOCK* AddNPCGunFlashEffect(VECTORCH *position, MATRIXCH* orientation, enum SFX_ID sfxID);
void RemoveNPCGunFlashEffect(DISPLAYBLOCK* dPtr);
void MaintainNPCGunFlashEffect(DISPLAYBLOCK* dPtr, VECTORCH *position, MATRIXCH* orientation);
int Validate_Target(STRATEGYBLOCK *target,char *SBname);
int Validate_Strategy(STRATEGYBLOCK *target,char *SBname);
AIMODULE *NearNPC_GetTargetAIModuleForRetreat(STRATEGYBLOCK *sbPtr, NPC_MOVEMENTDATA *moveData);
extern void InitSquad(void);
extern void DoSquad(void);
extern void ZoneAlert(int level,AIMODULE *targetModule);
extern void Marine_CorpseSightingTest(STRATEGYBLOCK *corpse);
#ifdef __cplusplus
}
#endif
#endif

236
src/avp/bh_mission.c Normal file
View file

@ -0,0 +1,236 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "bh_types.h"
#include "bh_mission.h"
#include "ourasert.h"
extern void MissionObjectiveTriggered(void* mission_objective);
extern void MakeMissionVisible(void* mission_objective);
extern void MakeMissionPossible(void* mission_objective);
void * MissionCompleteBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
MISSION_COMPLETE_BEHAV_BLOCK* m_bhv;
MISSION_COMPLETE_TOOLS_TEMPLATE* mc_tt;
GLOBALASSERT(sbptr);
m_bhv=(MISSION_COMPLETE_BEHAV_BLOCK*)AllocateMem(sizeof(MISSION_COMPLETE_BEHAV_BLOCK));
if(!m_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
mc_tt= (MISSION_COMPLETE_TOOLS_TEMPLATE*) bhdata;
m_bhv->bhvr_type=I_BehaviourMissionComplete;
sbptr->shapeIndex = 0;
COPY_NAME(sbptr->SBname, mc_tt->nameID);
m_bhv->mission_objective_ptr=mc_tt->mission_objective_ptr;
return((void*)m_bhv);
}
#define MissionTrigger_MakeVisible 0x00000001
#define MissionTrigger_MakePossible 0x00000002
#define MissionTrigger_DontComplete 0x00000004
void SendRequestToMissionStrategy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data)
{
MISSION_COMPLETE_BEHAV_BLOCK *mc_bhv;
GLOBALASSERT(sbptr);
GLOBALASSERT(sbptr->SBdataptr);
mc_bhv = (MISSION_COMPLETE_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((mc_bhv->bhvr_type == I_BehaviourMissionComplete));
if(!state) return;
if(extended_data & MissionTrigger_MakeVisible)
{
MakeMissionVisible(mc_bhv->mission_objective_ptr);
}
if(extended_data & MissionTrigger_MakePossible)
{
MakeMissionPossible(mc_bhv->mission_objective_ptr);
}
if(!(extended_data & MissionTrigger_DontComplete))
{
MissionObjectiveTriggered(mc_bhv->mission_objective_ptr);
}
}
void * MessageBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
MESSAGE_BEHAV_BLOCK* m_bhv;
MESSAGE_TOOLS_TEMPLATE* m_tt;
GLOBALASSERT(sbptr);
m_bhv=(MESSAGE_BEHAV_BLOCK*)AllocateMem(sizeof(MESSAGE_BEHAV_BLOCK));
if(!m_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
m_tt= (MESSAGE_TOOLS_TEMPLATE*) bhdata;
m_bhv->bhvr_type=I_BehaviourMessage;
sbptr->shapeIndex = 0;
COPY_NAME(sbptr->SBname, m_tt->nameID);
m_bhv->string_no=m_tt->string_no;
m_bhv->active=m_tt->active;
return((void*)m_bhv);
}
#define TextMessageRequest_Activate 1
#define TextMessageRequest_ActivateAndDisplay 2
void SendRequestToMessageStrategy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data)
{
MESSAGE_BEHAV_BLOCK *m_bhv;
GLOBALASSERT(sbptr);
GLOBALASSERT(sbptr->SBdataptr);
m_bhv = (MESSAGE_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((m_bhv->bhvr_type == I_BehaviourMessage));
switch(extended_data)
{
case TextMessageRequest_Activate :
m_bhv->active=state;
break;
case TextMessageRequest_ActivateAndDisplay :
m_bhv->active=state;
if(m_bhv->active)
{
PrintStringTableEntryInConsole(m_bhv->string_no);
StartTriggerPlotFMV(m_bhv->string_no);
}
break;
default :
if(m_bhv->active && state)
{
PrintStringTableEntryInConsole(m_bhv->string_no);
StartTriggerPlotFMV(m_bhv->string_no);
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct message_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BOOL active;
}MESSAGE_SAVE_BLOCK;
void LoadStrategy_Message(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
MESSAGE_BEHAV_BLOCK* m_bhv;
MESSAGE_SAVE_BLOCK* block = (MESSAGE_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourMessage) return;
m_bhv = (MESSAGE_BEHAV_BLOCK *)sbPtr->SBdataptr;
//start copying stuff
m_bhv->active = block->active;
}
void SaveStrategy_Message(STRATEGYBLOCK* sbPtr)
{
MESSAGE_BEHAV_BLOCK* m_bhv;
MESSAGE_SAVE_BLOCK* block;
m_bhv = (MESSAGE_BEHAV_BLOCK *)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
block->active = m_bhv->active;
}
/*------------------------------**
** Loading/Saving mission state **
**------------------------------*/
extern int GetMissionStateForSave(void* mission_objective);
extern void SetMissionStateFromLoad(void* mission_objective,int state);
typedef struct mission_complete_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
int state;
}MISSION_COMPLETE_SAVE_BLOCK;
void LoadStrategy_MissionComplete(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
MISSION_COMPLETE_BEHAV_BLOCK* m_bhv;
MISSION_COMPLETE_SAVE_BLOCK* block = (MISSION_COMPLETE_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourMissionComplete) return;
m_bhv = (MISSION_COMPLETE_BEHAV_BLOCK *)sbPtr->SBdataptr;
//start copying stuff
SetMissionStateFromLoad(m_bhv->mission_objective_ptr , block->state);
}
void SaveStrategy_MissionComplete(STRATEGYBLOCK* sbPtr)
{
MISSION_COMPLETE_BEHAV_BLOCK* m_bhv;
MISSION_COMPLETE_SAVE_BLOCK* block;
m_bhv = (MISSION_COMPLETE_BEHAV_BLOCK *)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
block->state = GetMissionStateForSave(m_bhv->mission_objective_ptr);
}

50
src/avp/bh_mission.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef bh_mission_h_
#define bh_mission_h 1
void * MissionCompleteBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr);
void * MessageBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr);
extern void ResetMission(void* mission_objective);
extern void PrintStringTableEntryInConsole(enum TEXTSTRING_ID string_id);
extern void SendRequestToMessageStrategy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data);
extern void SendRequestToMissionStrategy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data);
//when this strategy receives a request state of 1 it notifies its attached mission that
//it has been achieved
typedef struct mission_complete_tools_template
{
void* mission_objective_ptr;
char nameID [SB_NAME_LENGTH];
}MISSION_COMPLETE_TOOLS_TEMPLATE;
typedef struct mission_complete_target
{
AVP_BEHAVIOUR_TYPE bhvr_type;
void* mission_objective_ptr;
}MISSION_COMPLETE_BEHAV_BLOCK;
//this strategy displays its message upon receiving a request state of 1
typedef struct message_tools_template
{
enum TEXTSTRING_ID string_no;
char nameID [SB_NAME_LENGTH];
BOOL active;
}MESSAGE_TOOLS_TEMPLATE;
typedef struct message_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
enum TEXTSTRING_ID string_no;
BOOL active;
}MESSAGE_BEHAV_BLOCK;
#endif

3049
src/avp/bh_near.c Normal file

File diff suppressed because it is too large Load diff

2
src/avp/bh_near.h Normal file
View file

@ -0,0 +1,2 @@
extern void NearAlienBehaviour(STRATEGYBLOCK *sbPtr);

1196
src/avp/bh_paq.c Normal file

File diff suppressed because it is too large Load diff

103
src/avp/bh_paq.h Normal file
View file

@ -0,0 +1,103 @@
/* Patrick 18/2/97 ------------------------------------------------
Header file for alien queen and predator-alien support functions
-----------------------------------------------------------------*/
#ifndef _bhpaq_h_
#define _bhpaq_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_pred.h"
/* Patrick 18/2/97 ------------------------------------------------
Some enumerations
-----------------------------------------------------------------*/
typedef enum PaqSequence
{
PaqSQ_Run,
PaqSQ_Attack,
PaqSQ_Stand,
PaqSQ_Dying,
PaqSQ_Dead,
PaqSQ_Attack2,
}PAQ_SEQUENCE;
typedef enum paq_far_bhstate
{
PAQFS_Wait,
PAQFS_Hunt,
PAQFS_Wander,
PAQFS_Dying,
}PAQ_FAR_BHSTATE;
typedef enum paq_near_bhstate
{
PAQNS_Wait,
PAQNS_Approach,
PAQNS_Attack,
PAQNS_Wander,
PAQNS_Avoidance,
PAQNS_Dying,
}PAQ_NEAR_BHSTATE;
/* Patrick 18/2/97 ------------------------------------------------
Some structures
-----------------------------------------------------------------*/
typedef struct paqStatusBlock
{
signed int health;
signed int nearSpeed;
signed int damageInflicted;
PAQ_FAR_BHSTATE FarBehaviourState;
PAQ_NEAR_BHSTATE NearBehaviourState;
int stateTimer;
SHAPEANIMATIONCONTROLLER ShpAnimCtrl;
HMODELCONTROLLER HModelController;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
}PAQ_STATUS_BLOCK;
typedef struct tools_data_paq
{
struct vectorch position;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
}TOOLS_DATA_PAQ;
/* Patrick 18/2/97 ------------------------------------------------
Some defines
-----------------------------------------------------------------*/
#define PRAL_STARTING_HEALTH 700
#define QUEEN_STARTING_HEALTH 1400
#define NO_OF_FRAGMENTS_FROM_DEAD_PAQ 10
#define PRAL_NEAR_SPEED 10000 /* mm/s */
#define QUEEN_NEAR_SPEED 12000 /* mm/s */
#define PRAL_NEAR_DAMAGE 20 /* mm/s */
#define QUEEN_NEAR_DAMAGE 40 /* mm/s */
#define PAQ_CLOSE_ATTACK_RANGE 1500 /* mm */
#define PAQ_NEAR_VIEW_WIDTH 500 /* mm */
/* 1-1.5 seconds in 16ths of a second */
#define PAQ_FAR_MOVE_TIME ((16+(FastRandom()&0x07))*(ONE_FIXED>>4))
#define PAQ_NEAR_CLOSEATTACK_TIME (ONE_FIXED>>1) /* 1/2 second */
/* random time between 1 and 2 seconds,in fixed point,with granularity 1/8th second */
#define PAQ_NEARWAITTIME (ONE_FIXED+((FastRandom()&0x7)*(ONE_FIXED>>3)))
#define PAQ_DIETIME (ONE_FIXED<<4)
/* Patrick 18/2/97 ------------------------------------------------
Some prototypes
-----------------------------------------------------------------*/
void InitPredAlBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void InitQueenBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void PAQBehaviour(STRATEGYBLOCK *sbPtr);
void MakePAQNear(STRATEGYBLOCK *sbPtr);
void MakePAQFar(STRATEGYBLOCK *sbPtr);
void PAQIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple);
#ifdef __cplusplus
}
#endif
#endif

369
src/avp/bh_pargen.c Normal file
View file

@ -0,0 +1,369 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_pargen.h"
#include "dynamics.h"
#include "pvisible.h"
#include "particle.h"
#include "lighting.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern char *ModuleCurrVisArray;
extern int NormalFrameTime;
//particles used by each particle type
static enum PARTICLE_ID ParticleUsed[PARGEN_TYPE_LAST]=
{
PARTICLE_SPARK,
PARTICLE_STEAM,
PARTICLE_BLACKSMOKE,
PARTICLE_PARGEN_FLAME
};
void* ParticleGeneratorBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
PARTICLE_GENERATOR_BEHAV_BLOCK* pargen;
PARTICLE_GENERATOR_TOOLS_TEMPLATE* pg_tt;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
pargen=(PARTICLE_GENERATOR_BEHAV_BLOCK*)AllocateMem(sizeof(PARTICLE_GENERATOR_BEHAV_BLOCK));
if(!pargen)
{
memoryInitialisationFailure = 1;
return 0;
}
pargen->bhvr_type=I_BehaviourParticleGenerator;
pg_tt=(PARTICLE_GENERATOR_TOOLS_TEMPLATE*)bhdata;
//copy stuff from tools template
COPY_NAME(sbptr->SBname, pg_tt->nameID);
pargen->position = pg_tt->position;
pargen->orientation = pg_tt->orientation;
pargen->type = pg_tt->type;
pargen->active = pg_tt->active;
pargen->sound = pg_tt->sound;
//find the generator's module
sbptr->containingModule=ModuleFromPosition(&(pargen->position),0);
GLOBALASSERT(sbptr->containingModule);
if(pargen->sound)
{
pargen->sound->playing=pargen->active;
}
//see if generator has a parent object
pargen->parent_sbptr=FindSBWithName(pg_tt->parentID);
if(pargen->parent_sbptr)
{
if(pargen->parent_sbptr->DynPtr)
{
//work out generator's relative position
MATRIXCH m=pargen->parent_sbptr->DynPtr->OrientMat;
TransposeMatrixCH(&m);
pargen->relative_position=pargen->position;
pargen->relative_orientation=pargen->orientation;
SubVector(&pargen->parent_sbptr->DynPtr->Position,&pargen->relative_position);
RotateVector(&pargen->relative_position,&m);
MatrixMultiply(&pargen->relative_orientation,&m,&pargen->relative_orientation);
}
else
{
//parent object has no dynamics block
//so it can't be used
pargen->parent_sbptr=0;
}
}
pargen->frequency=pg_tt->frequency;
pargen->timer=pargen->frequency;
pargen->probability=pg_tt->probability;
pargen->speed=pg_tt->speed;
return (void*)pargen;
}
void ParticleGeneratorBehaveFun(STRATEGYBLOCK* sbptr)
{
BOOL play_sound=FALSE;
PARTICLE_GENERATOR_BEHAV_BLOCK* pargen;
GLOBALASSERT(sbptr);
pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((pargen->bhvr_type == I_BehaviourParticleGenerator));
if(pargen->parent_sbptr)
{
//generator has parent object , update position
if(pargen->parent_sbptr->SBflags.destroyed_but_preserved)
{
//parent object destroyed
//switch off generator if active and return
if(pargen->active)
{
pargen->active=0;
if(pargen->sound)
{
//stop sound
Stop_Track_Sound(pargen->sound);
}
}
return;
}
else
{
DYNAMICSBLOCK *dynPtr = pargen->parent_sbptr->DynPtr;
GLOBALASSERT(dynPtr);
//update orientation
MatrixMultiply(&pargen->relative_orientation,&dynPtr->OrientMat,&pargen->orientation);
//update position
pargen->position=pargen->relative_position;
RotateVector(&pargen->position,&dynPtr->OrientMat);
AddVector(&dynPtr->Position,&pargen->position);
//update containing module from parent
sbptr->containingModule=pargen->parent_sbptr->containingModule;
}
}
if(pargen->active)
{
//update timer
pargen->timer-=NormalFrameTime;
if(pargen->sound)
{
//update sound
Update_Track_Sound(pargen->sound,&pargen->position);
}
if(!sbptr->containingModule)
{
sbptr->containingModule=ModuleFromPosition(&(pargen->position),0);
}
GLOBALASSERT(sbptr->containingModule);
if(ModuleCurrVisArray[(sbptr->containingModule->m_index)])
{
//if containing module is near create particles.
switch(pargen->type)
{
case PARGEN_TYPE_SPARK :
{
if(pargen->timer<0)
{
if((FastRandom() & 0xffff)<=pargen->probability)
{
//create sparks
//like MakeSprayOfSparks , but in z direction
int noOfSparks = 15;
do
{
VECTORCH velocity;
velocity.vx = (FastRandom()&2047)-1024;
velocity.vy = (FastRandom()&2047)-1024;
velocity.vz = (FastRandom()&2047);
RotateVector(&velocity,&pargen->orientation);
MakeParticle(&pargen->position,&velocity,ParticleUsed[pargen->type]);
}
while(--noOfSparks);
MakeLightElement(&pargen->position,LIGHTELEMENT_ELECTRICAL_SPARKS);
play_sound=TRUE;
}
}
}
break;
case PARGEN_TYPE_FLAME :
//add light effect
MakeLightElement(&pargen->position,LIGHTELEMENT_PARGEN_FLAME);
//and fall throgh to next section
case PARGEN_TYPE_STEAM :
case PARGEN_TYPE_BLACKSMOKE :
{
while(pargen->timer<0)
{
VECTORCH velocity;
VECTORCH position=pargen->position;
int offset;
pargen->timer+=pargen->frequency;
//get a velocity of magnitude in the region of speed
velocity.vx = ((FastRandom()&1023) - 512);
velocity.vy = ((FastRandom()&1023) - 512);
velocity.vz = MUL_FIXED(pargen->speed,(ONE_FIXED+(FastRandom()&0x3fff)));
RotateVector(&velocity,&pargen->orientation);
//allow particle to have had part of a frames movement already
offset=FastRandom()%NormalFrameTime;
position.vx+=MUL_FIXED(offset,velocity.vx);
position.vy+=MUL_FIXED(offset,velocity.vy);
position.vz+=MUL_FIXED(offset,velocity.vz);
MakeParticle(&position,&velocity,ParticleUsed[pargen->type]);
}
}
break;
}
}
if(pargen->timer<0)
{
pargen->timer=pargen->frequency+(pargen->timer % pargen->frequency);
}
}
if(play_sound)
{
//if the generator has a non-looping sound , we should play it now
if(pargen->sound && !pargen->sound->loop)
{
Start_Track_Sound(pargen->sound,&pargen->position);
}
}
}
void SendRequestToParticleGenerator(STRATEGYBLOCK* sbptr,BOOL state,int extended_data)
{
PARTICLE_GENERATOR_BEHAV_BLOCK* pargen = sbptr->SBdataptr;
LOCALASSERT(pargen);
if(state)
{
//if generator has a parent object that has been destroyed , then it can't be switched on
if(pargen->parent_sbptr && pargen->parent_sbptr->SBflags.destroyed_but_preserved)
{
return;
}
pargen->active=1;
if(pargen->sound && pargen->sound->loop)
{
//start sound
Start_Track_Sound(pargen->sound,&pargen->position);
}
}
else
{
pargen->active=0;
if(pargen->sound)
{
//stop sound
Stop_Track_Sound(pargen->sound);
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct particle_generator_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
VECTORCH position;
MATRIXCH orientation;
VECTORCH relative_position; //relative to parent object (if it exists)
MATRIXCH relative_orientation; //relative to parent object (if it exists)
int timer; //time left to next particle burst
unsigned int active :1; //is generator currently active
unsigned int sound_playing :1;
}PARTICLE_GENERATOR_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV pargen
void LoadStrategy_ParticleGenerator(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
PARTICLE_GENERATOR_BEHAV_BLOCK* pargen;
PARTICLE_GENERATOR_SAVE_BLOCK* block = (PARTICLE_GENERATOR_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourParticleGenerator) return;
pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(position)
COPYELEMENT_LOAD(orientation)
COPYELEMENT_LOAD(relative_position)
COPYELEMENT_LOAD(relative_orientation)
COPYELEMENT_LOAD(timer)
COPYELEMENT_LOAD(active)
if(pargen->sound)
{
pargen->sound->playing = block->sound_playing;
Load_SoundState(&pargen->sound->activ_no);
}
}
void SaveStrategy_ParticleGenerator(STRATEGYBLOCK* sbPtr)
{
PARTICLE_GENERATOR_SAVE_BLOCK *block;
PARTICLE_GENERATOR_BEHAV_BLOCK* pargen;
pargen = (PARTICLE_GENERATOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(position)
COPYELEMENT_SAVE(orientation)
COPYELEMENT_SAVE(relative_position)
COPYELEMENT_SAVE(relative_orientation)
COPYELEMENT_SAVE(timer)
COPYELEMENT_SAVE(active)
if(pargen->sound)
{
block->sound_playing = pargen->sound->playing;
Save_SoundState(&pargen->sound->activ_no);
}
}

81
src/avp/bh_pargen.h Normal file
View file

@ -0,0 +1,81 @@
#ifndef _bh_pargen_h
#define _bh_pargen_h 1
#ifdef __cplusplus
extern "C" {
#endif
#include "track.h"
extern void* ParticleGeneratorBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void ParticleGeneratorBehaveFun(STRATEGYBLOCK* sbptr);
extern void SendRequestToParticleGenerator(STRATEGYBLOCK* sbptr,BOOL state,int extended_data);
typedef enum particle_generator_type
{
PARGEN_TYPE_SPARK,
PARGEN_TYPE_STEAM,
PARGEN_TYPE_BLACKSMOKE,
PARGEN_TYPE_FLAME,
PARGEN_TYPE_LAST
}PARTICLE_GENERATOR_TYPE;
typedef struct particle_generator_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH position;
MATRIXCH orientation;
VECTORCH relative_position; //relative to parent object (if it exists)
MATRIXCH relative_orientation; //relative to parent object (if it exists)
PARTICLE_GENERATOR_TYPE type;//particle generator type
TRACK_SOUND* sound; //not actually a track , but it will do
STRATEGYBLOCK* parent_sbptr;
int timer; //time left to next particle burst
int frequency; //time between bursts
int probability; //probability of particles (0 - 65536)
int speed; //mm/second
unsigned int active :1; //is generator currently active
}PARTICLE_GENERATOR_BEHAV_BLOCK;
typedef struct particle_generator_tools_template
{
char nameID[SB_NAME_LENGTH];
char parentID[SB_NAME_LENGTH];
VECTORCH position;
MATRIXCH orientation;
PARTICLE_GENERATOR_TYPE type;//particle generator type
TRACK_SOUND* sound; //not actually a track , but it will do
int frequency; //time between bursts
int probability; //probability of particles (0 - 65536)
int speed; //mm/second
unsigned int active :1;
}PARTICLE_GENERATOR_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

456
src/avp/bh_plachier.c Normal file
View file

@ -0,0 +1,456 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "dynamics.h"
#include "bh_plachier.h"
#include "ourasert.h"
#include "jsndsup.h"
#include "psndplat.h"
extern MODULEMAPBLOCK VisibilityDefaultObjectMap;
/*
void PlacedHierarchyRestart(PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv)
{
}
void PlacedHierarchyStop(PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv)
{
}
*/
SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char *);
void* PlacedHierarchyBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
PLACED_HIERARCHY_BEHAV_BLOCK* ph_bhv;
PLACED_HIERARCHY_TOOLS_TEMPLATE* ph_tt;
SECTION *root_section;
SECTION_DATA* sound_section_data;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
ph_bhv=(PLACED_HIERARCHY_BEHAV_BLOCK*)AllocateMem(sizeof(PLACED_HIERARCHY_BEHAV_BLOCK));
if(!ph_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
ph_bhv->bhvr_type=I_BehaviourPlacedHierarchy;
ph_tt=(PLACED_HIERARCHY_TOOLS_TEMPLATE*)bhdata;
sbptr->shapeIndex=0;
COPY_NAME(sbptr->SBname, ph_tt->nameID);
sbptr->DynPtr->Position = sbptr->DynPtr->PrevPosition = ph_tt->position;
sbptr->DynPtr->OrientEuler = ph_tt->orientation;
CreateEulerMatrix(&sbptr->DynPtr->OrientEuler, &sbptr->DynPtr->OrientMat);
TransposeMatrixCH(&sbptr->DynPtr->OrientMat);
ph_bhv->num_sequences=ph_tt->num_sequences;
ph_bhv->sequences=ph_tt->sequences;
ph_bhv->num_sounds=ph_tt->num_sounds;
ph_bhv->sounds=ph_tt->sounds;
ph_bhv->num_special_track_points=ph_tt->num_special_track_points;
ph_bhv->special_track_points=ph_tt->special_track_points;
root_section=GetNamedHierarchyFromLibrary(ph_tt->file_name,ph_tt->hier_name);
GLOBALASSERT(root_section);
Create_HModel(&ph_bhv->HModelController,root_section);
ph_bhv->current_seq=ph_tt->first_sequence;
InitHModelSequence(&ph_bhv->HModelController,ph_bhv->current_seq->sequence_no,ph_bhv->current_seq->sub_sequence_no,ph_bhv->current_seq->time);
ph_bhv->HModelController.Playing=ph_tt->playing;
ph_bhv->HModelController.Looped=ph_bhv->current_seq->loop;
//find the hierarchy section that sound should be produced from
sound_section_data=GetThisSectionData(ph_bhv->HModelController.section_data,"SoundSource");
if(!sound_section_data)
{
//if there isn't a SoundSource object , sound can come from the root section
sound_section_data=ph_bhv->HModelController.section_data;
}
ph_bhv->sound_location=&sound_section_data->World_Offset;
return ((void*)ph_bhv);
}
void MakePlacedHierarchyNear(STRATEGYBLOCK* sbptr)
{
MODULE tempModule;
DISPLAYBLOCK *dPtr;
DYNAMICSBLOCK *dynPtr = sbptr->DynPtr;
PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv= (PLACED_HIERARCHY_BEHAV_BLOCK*)(sbptr->SBdataptr);
LOCALASSERT(dynPtr);
LOCALASSERT(sbPtr->SBdptr == NULL);
VisibilityDefaultObjectMap.MapShape = 0;
tempModule.m_mapptr = &VisibilityDefaultObjectMap;
tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
tempModule.m_numlights = 0;
tempModule.m_lightarray = (struct lightblock *)0;
tempModule.m_extraitemdata = (struct extraitemdata *)0;
tempModule.m_dptr = NULL; /* this is important */
#if SupportWIndows95
tempModule.name = NULL; /* this is important */
#endif
AllocateModuleObject(&tempModule);
dPtr = tempModule.m_dptr;
if(dPtr==NULL) return; /* cannot create displayblock, so leave object "far" */
sbptr->SBdptr = dPtr;
dPtr->ObStrategyBlock = sbptr;
dPtr->ObMyModule = NULL;
/* also need to initialise positional information in the new display
block from the existing dynamics block: this necessary because this
function is (usually) called between the dynamics and rendering systems
so it is not initialised by the dynamics system the first time it is
drawn. */
dPtr->ObWorld = dynPtr->Position;
dPtr->ObEuler = dynPtr->OrientEuler;
dPtr->ObMat = dynPtr->OrientMat;
dPtr->HModelControlBlock=&ph_bhv->HModelController;
ProveHModel(dPtr->HModelControlBlock,dPtr);
}
void PlacedHierarchyBehaveFun(STRATEGYBLOCK* sbptr)
{
PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv;
GLOBALASSERT(sbptr);
ph_bhv =(PLACED_HIERARCHY_BEHAV_BLOCK*) sbptr->SBdataptr;
GLOBALASSERT((ph_bhv->bhvr_type) == I_BehaviourPlacedHierarchy);
if(sbptr->SBdptr)
{
ProveHModel(&ph_bhv->HModelController,sbptr->SBdptr);
}
else
{
ProveHModel_Far(&ph_bhv->HModelController,sbptr);
}
//update sound
if(ph_bhv->HModelController.Playing && ph_bhv->current_seq)
{
int i,j;
int timer=ph_bhv->HModelController.sequence_timer;
int keyframe_flags=ph_bhv->HModelController.keyframe_flags;
if(keyframe_flags)
{
for(i=0;i<ph_bhv->num_special_track_points;i++)
{
if(keyframe_flags & ph_bhv->special_track_points[i].track_point_no)
{
SPECIAL_TRACK_POINT* stp=&ph_bhv->special_track_points[i];
for(j=0;j<stp->num_targets;j++)
{
TRACK_POINT_TARGET* tpt=&stp->targets[j];
RequestState(tpt->target_sbptr,tpt->request,0);
}
}
}
}
for(i=0;i<ph_bhv->current_seq->num_sound_times;i++)
{
PLACED_HIERARCHY_SOUND_TIMES* s_time=&ph_bhv->current_seq->sound_times[i];
if(s_time->sound)
{
PLACED_HIERARCHY_SOUND* sound=s_time->sound;
//not much point in continuing if the sound wasn't loaded anyway
if(sound->sound_loaded)
{
if(timer>=s_time->start_time && timer<s_time->end_time)
{
//start sound if not already playing
if(!sound->playing)
{
int dist=VectorDistance(&Player->ObWorld,ph_bhv->sound_location);
if(dist<=sound->outer_range) //make sure sound is in range
{
SOUND3DDATA s3d;
s3d.position = *ph_bhv->sound_location;
s3d.inner_range = sound->inner_range;
s3d.outer_range = sound->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
if(s_time->sound->loop)
{
Sound_Play ((SOUNDINDEX)sound->sound_loaded->sound_num, "nvpel", &s3d,sound->max_volume,sound->pitch,&sound->activ_no);
}
else
{
Sound_Play ((SOUNDINDEX)sound->sound_loaded->sound_num, "nvpe", &s3d,sound->max_volume,sound->pitch,&sound->activ_no);
}
}
sound->playing=1;
}
//otherwise update its position
else
{
int dist=VectorDistance(&Player->ObWorld,ph_bhv->sound_location);
if(sound->activ_no!=SOUND_NOACTIVEINDEX)
{
if(dist<=sound->outer_range)
{
SOUND3DDATA s3d;
s3d.position = *ph_bhv->sound_location;
s3d.inner_range = sound->inner_range;
s3d.outer_range = sound->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
Sound_UpdateNew3d (sound->activ_no, &s3d);
}
else
{
Sound_Stop(sound->activ_no);
}
}
else
{
if(dist<=sound->outer_range && sound->loop)
{
SOUND3DDATA s3d;
s3d.position = *ph_bhv->sound_location;
s3d.inner_range = sound->inner_range;
s3d.outer_range = sound->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
Sound_Play ((SOUNDINDEX)sound->sound_loaded->sound_num, "nvpel", &s3d,sound->max_volume,sound->pitch,&sound->activ_no);
}
}
}
}
else
{
//stop sound
if(sound->activ_no!=SOUND_NOACTIVEINDEX)
{
Sound_Stop(sound->activ_no);
}
sound->playing=0;
}
}
}
}
}
}
void DeletePlacedHierarchy(PLACED_HIERARCHY_BEHAV_BLOCK* ph_bhv)
{
int i;
if(!ph_bhv) return;
for(i=0;i<ph_bhv->num_sounds;i++)
{
if(ph_bhv->sounds[i].activ_no!=SOUND_NOACTIVEINDEX)
{
Sound_Stop(ph_bhv->sounds[i].activ_no);
}
}
Dispel_HModel(&ph_bhv->HModelController);
}
void PlacedHierarchyStopSequence(PLACED_HIERARCHY_BEHAV_BLOCK* ph_bhv)
{
int i;
//stop hierarchy from playing
ph_bhv->HModelController.Playing=FALSE;
//and stop all the sounds
for(i=0;i<ph_bhv->num_sounds;i++)
{
if(ph_bhv->sounds[i].activ_no!=SOUND_NOACTIVEINDEX)
{
Sound_Stop(ph_bhv->sounds[i].activ_no);
}
ph_bhv->sounds[i].playing=0;
}
}
void SendRequestToPlacedHierarchy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data)
{
PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv;
int seq_num;
GLOBALASSERT(sbptr);
GLOBALASSERT(sbptr->SBdataptr);
ph_bhv = (PLACED_HIERARCHY_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((ph_bhv->bhvr_type == I_BehaviourPlacedHierarchy));
seq_num=(extended_data>>7)&0xff;
if(state)
{
PLACED_HIERARCHY_SEQUENCE* new_sequence;
GLOBALASSERT(seq_num<ph_bhv->num_sequences);
new_sequence=&ph_bhv->sequences[seq_num];
GLOBALASSERT(new_sequence->sequence_no!=-1);
if(new_sequence==ph_bhv->current_seq)
{
//restart the current sequence
ph_bhv->HModelController.Playing=1;
}
else
{
//stop the current sequence
PlacedHierarchyStopSequence(ph_bhv);
//start the new sequence
ph_bhv->current_seq=new_sequence;
InitHModelSequence(&ph_bhv->HModelController,ph_bhv->current_seq->sequence_no,ph_bhv->current_seq->sub_sequence_no,ph_bhv->current_seq->time);
ph_bhv->HModelController.Playing=1;
ph_bhv->HModelController.Looped=ph_bhv->current_seq->loop;
}
}
else
{
PlacedHierarchyStopSequence(ph_bhv);
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
void LoadStrategy_PlacedHierarchy(SAVE_BLOCK_STRATEGY_HEADER* header)
{
int i;
STRATEGYBLOCK* sbPtr;
PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv;
char * buffer =(char*) header;
buffer+=sizeof(*header);
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourPlacedHierarchy) return;
ph_bhv = (PLACED_HIERARCHY_BEHAV_BLOCK*)sbPtr->SBdataptr;
{
int sequence_index;
sequence_index = *(int*) buffer;
buffer+=sizeof(int);
if(sequence_index>=0 && sequence_index<ph_bhv->num_sequences)
{
ph_bhv->current_seq = &ph_bhv->sequences[sequence_index];
}
}
{
int loaded_num_sounds;
loaded_num_sounds = *(int*) buffer;
buffer +=sizeof(int);
for(i=0;i<loaded_num_sounds && i<ph_bhv->num_sounds;i++)
{
int playing;
playing = *(int*)buffer;
buffer += sizeof(int);
ph_bhv->sounds[i].playing = playing;
}
}
//load the hierarchy
{
SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
if(hier_header)
{
LoadHierarchy(hier_header,&ph_bhv->HModelController);
}
}
for(i=0;i<ph_bhv->num_sounds;i++)
{
Load_SoundState(&ph_bhv->sounds[i].activ_no);
}
}
void SaveStrategy_PlacedHierarchy(STRATEGYBLOCK* sbPtr)
{
PLACED_HIERARCHY_BEHAV_BLOCK *ph_bhv;
SAVE_BLOCK_STRATEGY_HEADER* header;
char* buffer;
unsigned int size;
int i;
ph_bhv = (PLACED_HIERARCHY_BEHAV_BLOCK*)sbPtr->SBdataptr;
//determine memeory required
size = sizeof(SAVE_BLOCK_STRATEGY_HEADER)+(2*sizeof(int))+(sizeof(int)*ph_bhv->num_sounds);
header = (SAVE_BLOCK_STRATEGY_HEADER*) GetPointerForSaveBlock(size);
buffer = (char*) header;
buffer += sizeof(*header);
//fill in the header
header->type = SaveBlock_Strategy;
header->size = size;
header->bhvr_type = I_BehaviourPlacedHierarchy;
COPY_NAME(header->SBname,sbPtr->SBname);
{
int sequence_index = ph_bhv->current_seq-ph_bhv->sequences;
*(int*)buffer = sequence_index;
buffer+=sizeof(int);
}
*(int*)buffer = ph_bhv->num_sounds;
buffer+=sizeof(int);
for(i=0;i<ph_bhv->num_sounds;i++)
{
int playing = ph_bhv->sounds[i].playing;
*(int*)buffer = playing;
buffer+=sizeof(int);
}
//save the hierarchy
SaveHierarchy(&ph_bhv->HModelController);
for(i=0;i<ph_bhv->num_sounds;i++)
{
Save_SoundState(&ph_bhv->sounds[i].activ_no);
}
}

104
src/avp/bh_plachier.h Normal file
View file

@ -0,0 +1,104 @@
#ifndef _bh_plachier_h_
#define _bh_plachier_h_ 1
#include "bh_track.h" //for the special_track_point structure
#ifdef __cplusplus
extern "C" {
#endif
typedef struct placed_hierarchy_sound
{
unsigned long inner_range;
unsigned long outer_range;
int max_volume;
int pitch;
struct loaded_sound const * sound_loaded;
int activ_no;
unsigned int loop:1;
unsigned int playing:1; //sound should be playing (if in range)
}PLACED_HIERARCHY_SOUND;
typedef struct placed_hierarchy_sound_times
{
int start_time;
int end_time;
PLACED_HIERARCHY_SOUND* sound;
}PLACED_HIERARCHY_SOUND_TIMES;
typedef struct placed_hierarchy_sequence
{
int sequence_no;
int sub_sequence_no;
int time;
unsigned int loop:1;
int num_sound_times;
PLACED_HIERARCHY_SOUND_TIMES* sound_times;
}PLACED_HIERARCHY_SEQUENCE;
typedef struct placed_hierarchy_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
HMODELCONTROLLER HModelController;
PLACED_HIERARCHY_SEQUENCE* current_seq;
int num_sequences;
PLACED_HIERARCHY_SEQUENCE* sequences;
VECTORCH* sound_location;
int num_sounds;
PLACED_HIERARCHY_SOUND* sounds;
int num_special_track_points;
SPECIAL_TRACK_POINT* special_track_points;
}PLACED_HIERARCHY_BEHAV_BLOCK;
typedef struct placed_hierarchy_tools_template
{
char nameID[SB_NAME_LENGTH];
VECTORCH position;
EULER orientation;
int num_sequences;
PLACED_HIERARCHY_SEQUENCE* sequences;
PLACED_HIERARCHY_SEQUENCE* first_sequence;
BOOL playing;
int num_sounds;
PLACED_HIERARCHY_SOUND* sounds;
int num_special_track_points;
SPECIAL_TRACK_POINT* special_track_points;
const char* file_name;
const char* hier_name;
}PLACED_HIERARCHY_TOOLS_TEMPLATE;
extern void* PlacedHierarchyBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr);
void PlacedHierarchyBehaveFun(STRATEGYBLOCK* sbptr);
void MakePlacedHierarchyNear(STRATEGYBLOCK* sbptr);
void DeletePlacedHierarchy(PLACED_HIERARCHY_BEHAV_BLOCK*);
void SendRequestToPlacedHierarchy(STRATEGYBLOCK* sbptr,BOOL state,int extended_data);
#ifdef __cplusplus
};
#endif
#endif

697
src/avp/bh_plift.c Normal file
View file

@ -0,0 +1,697 @@
/*------------------------------Patrick 14/3/97-----------------------------------
Source for Platform lift behaviour functions
--------------------------------------------------------------------------------*/
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "triggers.h"
#include "mslhand.h"
#include "dynblock.h"
#include "dynamics.h"
#include "showcmds.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "bh_plift.h"
#if SupportWindows95
/* for win95 net game support */
#include "pldnet.h"
#include "pldghost.h"
#endif
/* prototypes for this file */
static int SquashingSomething(DYNAMICSBLOCK *dynPtr);
static void PushPassengersUpwards(DYNAMICSBLOCK *dynPtr);
static int ActivatedByPlayer(DYNAMICSBLOCK *dynPtr);
static int PlayerIsNearOtherTerminal(STRATEGYBLOCK *sbPtr);
static int NetPlayerAtOtherTerminal(STRATEGYBLOCK *sbPtr);
static int PLiftIsNearerUpThanDown(STRATEGYBLOCK *sbPtr);
/* external globals used in this file */
extern int NormalFrameTime;
/*------------------------------Patrick 15/3/97-----------------------------------
Behaviour function for platform lift
--------------------------------------------------------------------------------*/
void PlatformLiftBehaviour(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
DYNAMICSBLOCK *dynPtr;
LOCALASSERT(sbPtr);
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
dynPtr = sbPtr->DynPtr;
LOCALASSERT(dynPtr);
switch(platformliftdata->state)
{
case(PLBS_AtRest):
{
if(AvP.Network==I_Host)
{
/* multiplayer host */
if(NetPlayerAtOtherTerminal(sbPtr))
{
if(platformliftdata->Enabled) ActivatePlatformLift(sbPtr);
}
else if(sbPtr->SBdptr)
{
/* check for activation by this player*/
if(ActivatedByPlayer(dynPtr))
{
if (platformliftdata->Enabled) ActivatePlatformLift(sbPtr);
}
}
}
else if(AvP.Network==I_No_Network)
{
/* single player */
if(sbPtr->SBdptr)
{
/* check for activation */
if(ActivatedByPlayer(dynPtr) || PlayerIsNearOtherTerminal(sbPtr))
{
if (platformliftdata->Enabled) ActivatePlatformLift(sbPtr);
}
}
}
else
{
#if SupportWindows95
LOCALASSERT(AvP.Network==I_Peer);
if(ActivatedByPlayer(dynPtr)) AddNetMsg_RequestPlatformLiftActivate(sbPtr);
#endif
}
//textprint("Platform state: at rest\n");
break;
}
case(PLBS_Activating):
{
if(AvP.Network!=I_Peer)
{
if(platformliftdata->activationDelayTimer>0)
{
platformliftdata->activationDelayTimer -= NormalFrameTime;
}
if(platformliftdata->activationDelayTimer<=0)
{
//play start sound if the lift has any
if(platformliftdata->start_sound)
{
Start_Track_Sound(platformliftdata->start_sound,&sbPtr->DynPtr->Position);
}
platformliftdata->activationDelayTimer = 0;
if(dynPtr->Position.vy > ((platformliftdata->upHeight+platformliftdata->downHeight)/2))
{
SendPlatformLiftUp(sbPtr);
}
else SendPlatformLiftDown(sbPtr);
}
}
//textprint("Platform state: activating\n");
//textprint("Platform timer: %d\n",platformliftdata->activationDelayTimer);
break;
}
case(PLBS_GoingUp):
{
if(dynPtr->Position.vy <= platformliftdata->upHeight)
{
/* finished */
StopPlatformLift(sbPtr);
if (platformliftdata->OneUse)
platformliftdata->Enabled = No;
}
else
{
sbPtr->DynPtr->Displacement.vy = -MUL_FIXED(PLATFORMLIFT_SPEED,NormalFrameTime);
{
int d = platformliftdata->upHeight - sbPtr->DynPtr->Position.vy;
if (d>sbPtr->DynPtr->Displacement.vy)
{
sbPtr->DynPtr->Displacement.vy=d;
}
}
}
PushPassengersUpwards(dynPtr);
//textprint("Platform state: going up\n");
break;
}
case(PLBS_GoingDown):
{
if(dynPtr->Position.vy >= platformliftdata->downHeight)
{
/* finished */
StopPlatformLift(sbPtr);
if (platformliftdata->OneUse)
platformliftdata->Enabled = No;
}
else
{
sbPtr->DynPtr->Displacement.vy = MUL_FIXED(PLATFORMLIFT_SPEED,NormalFrameTime);
{
int d = platformliftdata->downHeight - sbPtr->DynPtr->Position.vy;
if (d<sbPtr->DynPtr->Displacement.vy)
{
sbPtr->DynPtr->Displacement.vy=d;
}
}
if(AvP.Network!=I_Peer)
{
if(SquashingSomething(dynPtr))
{
// sbPtr->DynPtr->Displacement.vy = 0;
// SendPlatformLiftUp(sbPtr);
}
}
}
//textprint("Platform state: going down\n");
break;
}
default:
{
LOCALASSERT(1==0);
}
}
//update sound
if(platformliftdata->state==PLBS_GoingUp || platformliftdata->state==PLBS_GoingDown)
{
BOOL mainSoundShouldBePlaying=TRUE;
//the main sound should be started if there is no start sound , or the start sound has
//almost finished
if(platformliftdata->start_sound && platformliftdata->start_sound->playing)
{
Update_Track_Sound(platformliftdata->start_sound,&dynPtr->Position);
if(platformliftdata->start_sound->time_left>NormalFrameTime)
{
mainSoundShouldBePlaying=FALSE;
}
}
if(platformliftdata->sound)
{
if(platformliftdata->sound->playing)
{
Update_Track_Sound(platformliftdata->sound,&dynPtr->Position);
}
else if(mainSoundShouldBePlaying)
{
Start_Track_Sound(platformliftdata->sound,&sbPtr->DynPtr->Position);
}
}
}
//textprint("Platform pos: %d / %d / %d\n",platformliftdata->upHeight,dynPtr->Position.vy,platformliftdata->downHeight);
/* send state messages in net game */
#if SupportWindows95
if(AvP.Network==I_Host)
{
if(platformliftdata->netMsgCount>0)
{
/* don't send at rest messages: peers detect end of movement locally. */
if(platformliftdata->state!=PLBS_AtRest)
{
AddNetMsg_PlatformLiftState(sbPtr);
}
platformliftdata->netMsgCount--;
}
}
#endif
}
void InitialisePlatformLift(void* bhdata, STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_TOOLS_TEMPLATE *toolsData = (PLATFORMLIFT_TOOLS_TEMPLATE *)bhdata;
PLATFORMLIFT_BEHAVIOUR_BLOCK* platformliftdata;
int i;
LOCALASSERT(sbPtr->I_SBtype == I_BehaviourPlatform);
LOCALASSERT(toolsData);
/* create, initialise and attach a data block */
platformliftdata = (void *)AllocateMem(sizeof(PLATFORMLIFT_BEHAVIOUR_BLOCK));
if(!platformliftdata)
{
memoryInitialisationFailure = 1;
return;
}
sbPtr->SBdataptr = platformliftdata;
platformliftdata->homePosition = toolsData->position;
platformliftdata->activationDelayTimer = 0;
platformliftdata->state = PLBS_AtRest;
platformliftdata->netMsgCount = 0;
if(toolsData->travel<0)
{
platformliftdata->upHeight = platformliftdata->homePosition.vy + toolsData->travel;
platformliftdata->downHeight = platformliftdata->homePosition.vy;
}
else
{
platformliftdata->upHeight = platformliftdata->homePosition.vy;
platformliftdata->downHeight = platformliftdata->homePosition.vy + toolsData->travel;
}
LOCALASSERT(platformliftdata->upHeight < platformliftdata->downHeight);
platformliftdata->sound = toolsData->sound;
platformliftdata->start_sound = toolsData->start_sound;
platformliftdata->end_sound = toolsData->end_sound;
platformliftdata->Enabled = toolsData->Enabled;
platformliftdata->OneUse = toolsData->OneUse;
/* create and initialise the dynamics block */
{
DYNAMICSBLOCK *dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_PLATFORM_LIFT);
GLOBALASSERT(dynPtr);
sbPtr->DynPtr = dynPtr;
dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0;
dynPtr->OrientEuler = toolsData->orientation;
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
}
/* strategy block initialisation */
sbPtr->shapeIndex = toolsData->shapeIndex;
for(i=0;i<SB_NAME_LENGTH;i++) sbPtr->SBname[i] = toolsData->nameID[i];
sbPtr->integrity = 1;
}
/*------------------------------Patrick 2/4/97-----------------------------------
State change functions: these are alos used by network message processing fns
--------------------------------------------------------------------------------*/
void ActivatePlatformLift(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
platformliftdata->state = PLBS_Activating;
platformliftdata->activationDelayTimer = PLATFORMLIFT_ACTIVATIONTIME;
platformliftdata->netMsgCount = PLATFORMLIFT_NUMNETMESSAGES;
}
void SendPlatformLiftUp(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
platformliftdata->state = PLBS_GoingUp;
sbPtr->DynPtr->Displacement.vx = sbPtr->DynPtr->Displacement.vz = 0;
platformliftdata->netMsgCount = PLATFORMLIFT_NUMNETMESSAGES;
sbPtr->DynPtr->Displacement.vy = -MUL_FIXED(PLATFORMLIFT_SPEED,NormalFrameTime);
{
int d = platformliftdata->upHeight - sbPtr->DynPtr->Position.vy;
if (d>sbPtr->DynPtr->Displacement.vy)
{
sbPtr->DynPtr->Displacement.vy=d;
}
}
}
void SendPlatformLiftDown(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
platformliftdata->state = PLBS_GoingDown;
sbPtr->DynPtr->Displacement.vx = sbPtr->DynPtr->Displacement.vz = 0;
platformliftdata->netMsgCount = PLATFORMLIFT_NUMNETMESSAGES;
sbPtr->DynPtr->Displacement.vy = MUL_FIXED(PLATFORMLIFT_SPEED,NormalFrameTime);
{
int d = platformliftdata->downHeight - sbPtr->DynPtr->Position.vy;
if (d<sbPtr->DynPtr->Displacement.vy)
{
sbPtr->DynPtr->Displacement.vy=d;
}
}
}
void StopPlatformLift(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
sbPtr->DynPtr->Displacement.vx = sbPtr->DynPtr->Displacement.vy = sbPtr->DynPtr->Displacement.vz = 0;
platformliftdata->state = PLBS_AtRest;
/* just to stop drift... */
/*
if(PLiftIsNearerUpThanDown(sbPtr))
sbPtr->DynPtr->Position.vy = platformliftdata->upHeight;
else
sbPtr->DynPtr->Position.vy = platformliftdata->downHeight;
*/
platformliftdata->netMsgCount = PLATFORMLIFT_NUMNETMESSAGES;
//stop sound if the lift has any
if(platformliftdata->sound)
{
Stop_Track_Sound(platformliftdata->sound);
}
//start end sound if lift has any
if(platformliftdata->end_sound)
{
Start_Track_Sound(platformliftdata->end_sound,&sbPtr->DynPtr->Position);
}
}
/*------------------------------Patrick 15/3/97-----------------------------------
Support functions
--------------------------------------------------------------------------------*/
static int SquashingSomething(DYNAMICSBLOCK *dynPtr)
{
struct collisionreport *nextReport;
int squashingSomething = 0;
LOCALASSERT(dynPtr);
nextReport = dynPtr->CollisionReportPtr;
/* walk the collision report list, looking for collisions against objects */
while(nextReport)
{
STRATEGYBLOCK *sbPtr = nextReport->ObstacleSBPtr;
if(sbPtr)
{
if(nextReport->ObstacleNormal.vy < -46340)
{
extern DAMAGE_PROFILE FallingDamage;
squashingSomething=1;
/* squish! */
CauseDamageToObject(sbPtr, &FallingDamage, (100*NormalFrameTime), NULL);
}
else if (nextReport->ObstacleNormal.vy > 46340)
{
DYNAMICSBLOCK *objDynPtr = sbPtr->DynPtr;
if (objDynPtr)
{
if (objDynPtr->LinImpulse.vy < PLATFORMLIFT_SPEED)
{
objDynPtr->LinImpulse.vy = PLATFORMLIFT_SPEED;
}
}
}
}
nextReport = nextReport->NextCollisionReportPtr;
}
return squashingSomething;
}
static void PushPassengersUpwards(DYNAMICSBLOCK *dynPtr)
{
#if 0
struct collisionreport *nextReport;
LOCALASSERT(dynPtr);
nextReport = dynPtr->CollisionReportPtr;
/* walk the collision report list, looking for collisions against objects */
while(nextReport)
{
STRATEGYBLOCK *sbPtr = nextReport->ObstacleSBPtr;
if(sbPtr)
{
DYNAMICSBLOCK *objDynPtr = sbPtr->DynPtr;
if (objDynPtr)
{
int upwardsImpulse = -MUL_FIXED(GRAVITY_STRENGTH,NormalFrameTime) - PLATFORMLIFT_SPEED;
if (objDynPtr->LinImpulse.vy > upwardsImpulse)
{
objDynPtr->LinImpulse.vy = upwardsImpulse;
objDynPtr->IsInContactWithFloor =1;
PrintDebuggingText("I'M PUSHING UP AN OBJECT!");
}
}
}
nextReport = nextReport->NextCollisionReportPtr;
}
#endif
}
static int ActivatedByPlayer(DYNAMICSBLOCK *dynPtr)
{
struct collisionreport *nextReport;
LOCALASSERT(dynPtr);
nextReport = dynPtr->CollisionReportPtr;
/* walk the collision report list, looking for collisions against objects */
while(nextReport)
{
/// textprint("collision with %p\n",nextReport->ObstacleSBPtr);
if(nextReport->ObstacleSBPtr == Player->ObStrategyBlock) return 1;
nextReport = nextReport->NextCollisionReportPtr;
}
return 0;
}
static int PlayerIsNearOtherTerminal(STRATEGYBLOCK *sbPtr)
{
int averageHeight;
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
DYNAMICSBLOCK *dynPtr;
LOCALASSERT(sbPtr);
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
LOCALASSERT(platformliftdata->state == PLBS_AtRest);
dynPtr = sbPtr->DynPtr;
LOCALASSERT(dynPtr);
averageHeight = (platformliftdata->upHeight+platformliftdata->downHeight)/2;
if(dynPtr->Position.vy > averageHeight)
{
if (Player->ObStrategyBlock->DynPtr->Position.vy < averageHeight)
return 1;
}
else
{
if (Player->ObStrategyBlock->DynPtr->Position.vy > averageHeight)
return 1;
}
return 0;
}
/* returns 1 if the player or a remote player is within 5 m of the other end of
the lift track...*/
static int NetPlayerAtOtherTerminal(STRATEGYBLOCK *sbPtr)
{
#if SupportWindows95
extern int NumActiveStBlocks;
extern STRATEGYBLOCK *ActiveStBlockList[];
int sbIndex = 0;
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
DYNAMICSBLOCK *dynPtr;
VECTORCH otherTerminal;
LOCALASSERT(sbPtr);
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
LOCALASSERT(platformliftdata->state == PLBS_AtRest);
dynPtr = sbPtr->DynPtr;
LOCALASSERT(dynPtr);
if(PLiftIsNearerUpThanDown(sbPtr))
{
otherTerminal = dynPtr->Position;
otherTerminal.vy = platformliftdata->downHeight;
}
else
{
otherTerminal = dynPtr->Position;
otherTerminal.vy = platformliftdata->upHeight;
}
while(sbIndex < NumActiveStBlocks)
{
STRATEGYBLOCK *sbPtr = ActiveStBlockList[sbIndex++];
if(sbPtr->I_SBtype==I_BehaviourNetGhost)
{
NETGHOSTDATABLOCK *ghostData = ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
LOCALASSERT(ghostData);
if((ghostData->type==I_BehaviourMarinePlayer)||
(ghostData->type==I_BehaviourAlienPlayer)||
(ghostData->type==I_BehaviourPredatorPlayer))
{
/* remote player */
LOCALASSERT(sbPtr->DynPtr);
if(VectorDistance(&(sbPtr->DynPtr->Position),&(otherTerminal))<5000) return 1;
}
}
else if(sbPtr==Player->ObStrategyBlock)
{
/* local player */
LOCALASSERT(sbPtr->DynPtr);
if(VectorDistance(&(sbPtr->DynPtr->Position),&(otherTerminal))<5000) return 1;
}
}
return 0;
#else
return 0;
#endif
}
static int PLiftIsNearerUpThanDown(STRATEGYBLOCK *sbPtr)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
int upDist, downDist;
LOCALASSERT(sbPtr);
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
LOCALASSERT(sbPtr->DynPtr);
upDist = sbPtr->DynPtr->Position.vy - platformliftdata->upHeight;
downDist = platformliftdata->downHeight - sbPtr->DynPtr->Position.vy;
if(upDist<downDist) return 1;
else return 0;
}
void NetworkPeerChangePlatformLiftState(STRATEGYBLOCK* sbPtr,PLATFORMLIFT_STATES new_state)
{
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
LOCALASSERT(sbPtr);
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK *)sbPtr->SBdataptr;
LOCALASSERT(platformliftdata);
LOCALASSERT(sbPtr->DynPtr);
//check to see if this is a new state , and change any sound playing as necessary
if(new_state==PLBS_Activating)
{
/*
ignore this state change , since only the host does anything while the lift is
activating , and this will prevent the lift from stopping at the ends correctly
*/
return;
}
if((new_state==PLBS_GoingUp || new_state==PLBS_GoingUp) &&
!(platformliftdata->state==PLBS_GoingUp || platformliftdata->state==PLBS_GoingDown))
{
//platform lift has started moving
if(platformliftdata->start_sound)
{
Start_Track_Sound(platformliftdata->start_sound,&sbPtr->DynPtr->Position);
}
}
platformliftdata->state=new_state;
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct platform_lift_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
DYNAMICSBLOCK dynamics;
int activationDelayTimer;
PLATFORMLIFT_STATES state;
BOOL Enabled;
BOOL OneUse; //if set ,lift becomes disabled after changing position once
}PLATFORM_LIFT_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV platformliftdata
void LoadStrategy_PlatformLift(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
PLATFORM_LIFT_SAVE_BLOCK* block = (PLATFORM_LIFT_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourPlatform) return;
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(activationDelayTimer)
COPYELEMENT_LOAD(state)
COPYELEMENT_LOAD(Enabled)
COPYELEMENT_LOAD(OneUse)
*sbPtr->DynPtr = block->dynamics;
}
void SaveStrategy_PlatformLift(STRATEGYBLOCK* sbPtr)
{
PLATFORM_LIFT_SAVE_BLOCK *block;
PLATFORMLIFT_BEHAVIOUR_BLOCK *platformliftdata;
platformliftdata = (PLATFORMLIFT_BEHAVIOUR_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
COPYELEMENT_SAVE(activationDelayTimer)
COPYELEMENT_SAVE(state)
COPYELEMENT_SAVE(Enabled)
COPYELEMENT_SAVE(OneUse)
block->dynamics = *sbPtr->DynPtr;
block->dynamics.CollisionReportPtr=0;
}

61
src/avp/bh_plift.h Normal file
View file

@ -0,0 +1,61 @@
#include "track.h"
/*------------------------------Patrick 14/3/97-----------------------------------
Header for platform lift stuff
--------------------------------------------------------------------------------*/
typedef enum platformlift_states
{
PLBS_AtRest,
PLBS_Activating,
PLBS_GoingUp,
PLBS_GoingDown,
} PLATFORMLIFT_STATES;
typedef struct platformlift_behaviour_type
{
VECTORCH homePosition;
int upHeight;
int downHeight;
int activationDelayTimer;
PLATFORMLIFT_STATES state;
TRACK_SOUND* sound;
TRACK_SOUND* start_sound;
TRACK_SOUND* end_sound;
// A switch will set these flags on AssignSBNames
BOOL Enabled;
BOOL OneUse; //if set ,lift becomes disabled after changing position once
int netMsgCount;
} PLATFORMLIFT_BEHAVIOUR_BLOCK;
typedef struct platformlift_tools_template
{
struct vectorch position;
struct euler orientation;
int shapeIndex;
int travel; /* vertical distance from start position to end position (down = +ve) */
BOOL Enabled;
BOOL OneUse;
char nameID[SB_NAME_LENGTH];
TRACK_SOUND* sound;
TRACK_SOUND* start_sound;
TRACK_SOUND* end_sound;
} PLATFORMLIFT_TOOLS_TEMPLATE;
#define PLATFORMLIFT_SPEED 5000 /* mm/s */
#define PLATFORMLIFT_ACTIVATIONTIME ((ONE_FIXED*3)>>1) /* fixed point seconds */
#define PLATFORMLIFT_NUMNETMESSAGES 5
void InitialisePlatformLift(void* bhdata, STRATEGYBLOCK *sbPtr);
void PlatformLiftBehaviour(STRATEGYBLOCK *sbPtr);
void ActivatePlatformLift(STRATEGYBLOCK *sbPtr);
void SendPlatformLiftUp(STRATEGYBLOCK *sbPtr);
void SendPlatformLiftDown(STRATEGYBLOCK *sbPtr);
void StopPlatformLift(STRATEGYBLOCK *sbPtr);

7208
src/avp/bh_pred.c Normal file

File diff suppressed because it is too large Load diff

261
src/avp/bh_pred.h Normal file
View file

@ -0,0 +1,261 @@
/*--------------Patrick 21/1/97-----------------------
Header file for predator AI & NPC support functions
---------------------------------------------------*/
#ifndef _bhpred_h_
#define _bhpred_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_ais.h"
#include "decal.h"
/*-----------------------------
Predator Specific Support
-------------------------------*/
/* predator animation sequences */
typedef enum predatorsequence
{
PredSQ_Run=0,
PredSQ_Crawl,
PredSQ_Stand,
PredSQ_Crouch,
PredSQ_StandDie,
PredSQ_StandDead,
PredSQ_CrouchDie,
PredSQ_CrouchDead,
PredSQ_StandingSwipe,
PredSQ_CrouchedSwipe,
PredSQ_RunningSwipe,
PredSQ_CrawlingSwipe,
PredSQ_Jump,
PredSQ_Taunt,
PredSQ_Run_Backwards,
PredSQ_Crawl_Backwards,
PredSQ_RunningSwipe_Backwards,
PredSQ_CrawlingSwipe_Backwards,
PredSQ_BaseOfStaffAttacks=20,
PredSQ_BaseOfWristbladeAttacks=40,
}PREDATOR_SEQUENCE;
typedef enum pred_bhstate {
PBS_Wandering,
PBS_Hunting,
PBS_Avoidance,
PBS_Withdrawing,
PBS_Dying,
PBS_Recovering,
PBS_SwapWeapon,
PBS_Engaging,
PBS_Attacking,
PBS_Pathfinding,
PBS_Returning,
PBS_Taunting,
PBS_SelfDestruct,
} PRED_BHSTATE;
typedef enum pred_return_condition {
PRC_No_Change,
PRC_Request_Engage,
PRC_Request_Attack,
PRC_Request_Wander,
PRC_Request_Avoidance,
PRC_Request_Hunt,
PRC_Request_Withdraw,
PRC_Request_Recover,
PRC_Request_Swap,
PRC_Request_Return,
PRC_Request_Pathfind,
PRC_Request_Taunt,
PRC_Request_SelfDestruct,
} PRED_RETURN_CONDITION;
/* cloaking states */
typedef enum pred_cloakstate
{
PCLOAK_Off,
PCLOAK_Activating,
PCLOAK_On,
PCLOAK_Deactivating,
}PRED_CLOAKSTATE;
typedef struct predatorPersonalParameters
{
int startingHealth; /* initial health */
int speed; /* running speed */
int defenceHealth; /* health level below which defensive behaviour is used */
int useShoulderCannon; /* 1 = shouldercannon, 0 = disc */
int timeBetweenRangedAttacks;
int maxShotsPerRangedAttack;
int timeBetweenShots;
int closeAttackDamage;
int regenerationUnit; /* health recovered when made visible */
int chanceOfCloaking; /* 0-8, chance in 8 */
} PREDATOR_PERSONALPARAMETERS;
typedef enum predator_npc_weapons {
PNPCW_Pistol,
PNPCW_Wristblade,
PNPCW_PlasmaCaster,
PNPCW_Staff,
PNPCW_Medicomp,
PNPCW_Speargun,
PNPCW_SeriousPlasmaCaster,
PNPCW_End,
} PREDATOR_NPC_WEAPONS;
typedef struct predator_weapon_data {
PREDATOR_NPC_WEAPONS id;
PRED_RETURN_CONDITION (*WeaponFireFunction)(STRATEGYBLOCK *);
PRED_RETURN_CONDITION (*WeaponEngageFunction)(STRATEGYBLOCK *);
char *Riffname;
char *HierarchyName;
char *GunName;
char *ElevationName;
char *HitLocationTableName;
int MinRange;
int ForceFireRange;
int MaxRange;
int FiringRate;
int VolleySize;
int SwappingTime;
int UseElevation :1;
}PREDATOR_WEAPON_DATA;
typedef struct predatorStatusBlock
{
signed int health;
PRED_BHSTATE behaviourState;
PRED_BHSTATE lastState;
int stateTimer;
int internalState;
int patience;
int enableSwap;
int enableTaunt;
VECTORCH weaponTarget; /* target position for firing weapon at */
int volleySize; /* used for weapon control */
NPC_OBSTRUCTIONREPORT obstruction;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
NPC_AVOIDANCEMANAGER avoidanceManager;
WAYPOINT_MANAGER waypointManager;
int IAmCrouched;
int personalNumber; /* for predator personalisation */
int nearSpeed;
int GibbFactor;
int incidentFlag;
int incidentTimer;
PREDATOR_WEAPON_DATA *Selected_Weapon;
PREDATOR_NPC_WEAPONS PrimaryWeapon;
PREDATOR_NPC_WEAPONS SecondaryWeapon;
PREDATOR_NPC_WEAPONS ChangeToWeapon;
ATTACK_DATA *current_attack;
STRATEGYBLOCK *Target;
char Target_SBname[SB_NAME_LENGTH];
int soundHandle;
HMODELCONTROLLER HModelController;
SECTION_DATA *My_Gun_Section; /* For template computation. */
SECTION_DATA *My_Elevation_Section; /* For elevation computation. */
/* these are for cloaking... */
PRED_CLOAKSTATE CloakStatus;
int CloakingEffectiveness;
int CloakTimer;
/* And these for the laser dots. */
THREE_LASER_DOT_DESC Pred_Laser_Sight;
int Pred_Laser_On :1;
int Explode :1;
/* Pathfinder parameters */
int path;
int stepnumber;
AIMODULE *missionmodule;
AIMODULE *fearmodule;
/* Pathfinder parameters */
char death_target_ID[SB_NAME_LENGTH]; //another strategy can be notified of the marine's death
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
}PREDATOR_STATUS_BLOCK;
typedef struct dormantPredatorStatusBlock
{
AVP_BEHAVIOUR_TYPE bhvr_type;
void* toolsData;
}DORMANT_PREDATOR_STATUS_BLOCK;
/* Tools data template */
typedef struct tools_data_predator
{
struct vectorch position;
int shapeIndex;
int predator_number;
char nameID[SB_NAME_LENGTH];
PREDATOR_NPC_WEAPONS primary;
PREDATOR_NPC_WEAPONS secondary;
int path;
int stepnumber;
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
}TOOLS_DATA_PREDATOR;
#define PRED_SELF_DESTRUCT_TIMER (ONE_FIXED*3)
#define PRED_WALKING_SPEED_MAX (5000)
#define PRED_WALKING_SPEED_MIN (3000)
#define PRED_PATIENCE_TIME (6*ONE_FIXED)
#define PRED_REGEN_TIME (10*ONE_FIXED)
#define PRED_MAXIDENTITY (4)
#define NO_OF_FRAGMENTS_FROM_DEAD_PREDATOR (10)
#define PRED_CLOSE_ATTACK_RANGE (1500) /* mm */
#define PRED_STAFF_ATTACK_RANGE (2000) /* mm */
#define PRED_NEAR_VIEW_WIDTH (500) /* mm */
#define PRED_FPPLASMA_INFRONT (600) /* mm */
#define PRED_FPPLASMA_ACROSS (-500) /* mm */
#define PRED_FPPLASMA_UP (900) /* mm */
#define PRED_FPPLASMA_INFRONTCROUCH (600) /* mm */
#define PRED_FPPLASMA_ACROSSCROUCH (-500) /* mm */
#define PRED_FPPLASMA_UPCROUCH (400) /* mm */
#define PRED_FPDISC_INFRONT (600) /* mm */
#define PRED_FPDISC_ACROSS (500) /* mm */
#define PRED_FPDISC_UP (500) /* mm */
#define PRED_FPDISC_INFRONTCROUCH (600) /* mm */
#define PRED_FPDISC_ACROSSCROUCH (500) /* mm */
#define PRED_FPDISC_UPCROUCH (200) /* mm */
#define PRED_PLASBOLTSPEED (22000) /* mm/s */
#define PRED_PLASBOLTDAMAGE (50)
/* 1.5-2 seconds in 1/16 second. NB DO NOT INCREASE THIS */
#define PRED_FAR_MOVE_TIME ((24+(FastRandom()&0x07))*(ONE_FIXED>>4))
#define PRED_NEAR_CLOSEATTACK_TIME ONE_FIXED /* 1 second */
extern void InitPredatorBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
extern void InitDormantPredatorBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
extern void PredatorBehaviour(STRATEGYBLOCK *sbPtr);
extern void MakePredatorNear(STRATEGYBLOCK *sbPtr);
extern void MakePredatorFar(STRATEGYBLOCK *sbPtr);
extern void PredatorIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple,SECTION_DATA *Section, VECTORCH *incoming);
extern void ActivateDormantPredator(STRATEGYBLOCK *sbPtr);
extern int NPCPredatorIsCloaked(STRATEGYBLOCK *sbPtr);
extern void StartPredatorSelfDestructExplosion(STRATEGYBLOCK *sbPtr);
#ifdef __cplusplus
}
#endif
#endif

5173
src/avp/bh_queen.c Normal file

File diff suppressed because it is too large Load diff

141
src/avp/bh_queen.h Normal file
View file

@ -0,0 +1,141 @@
/* ChrisF 17/3/98 ------------------------------------------------
Header file for alien queen support functions
-----------------------------------------------------------------*/
#ifndef _bhqueen_h_
#define _bhqueen_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
#include "bh_pred.h"
#include "scream.h"
typedef enum queen_behaviour_state {
QBS_Command,
QBS_Waypoints,
QBS_Engagement,
QBS_GoingForObject,
QBS_CarryingObject,
QBS_Reconsider,
QBS_ClimbingOutOfAirlock,
QBS_Dead,
} QUEEN_BEHAVIOUR_STATE;
typedef enum queen_manoeuvre {
QM_Standby,
QM_StepForward,
QM_StepBack,
QM_TurnLeft,
QM_TurnRight,
QM_ComeToPoint,
QM_Taunt,
QM_Hiss,
QM_LeftSwipe,
QM_RightSwipe,
QM_Charge,
QM_Close,
QM_Jump,
QM_ButtCharge,
QM_ButtAttack,
QM_Stun,
QM_Climbing,
QM_ChangeFacing,
QM_ApproachWall,
} QUEEN_MANOEUVRE;
typedef enum queen_foot {
LeftFoot,
RightFoot,
} QUEEN_FOOT;
typedef struct tools_data_queen
{
struct vectorch position;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
}TOOLS_DATA_QUEEN;
typedef struct queenStatusBlock
{
QUEEN_BEHAVIOUR_STATE QueenState;
QUEEN_MANOEUVRE current_move;
QUEEN_MANOEUVRE next_move;
QUEEN_FOOT fixed_foot;
SECTION_DATA *fixed_foot_section;
VECTORCH fixed_foot_oldpos;
DELTA_CONTROLLER *attack_delta;
DELTA_CONTROLLER *hit_delta;
VECTORCH TargetPos;
int moveTimer;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
HMODELCONTROLLER HModelController;
char death_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
BOOL TempTarget;//going for an intermediate point
int TempTargetTimer;//time before queen gives up going for intermediate point
int CurrentQueenObject;
int QueenStateTimer;
int QueenObjectBias;
int QueenPlayerBias;
int QueenTauntTimer;
int QueenFireTimer;
VECTORCH LastVelocity;
SECTION_DATA* QueenRightHand;
STRATEGYBLOCK* QueenTargetSB;
BOOL BeenInAirlock;
BOOL QueenActivated; //queen is inactive until seen
BOOL TargetInfoValid; //have the next three items been set
int TargetDistance; //distance of current target from queen
int TargetRelSpeed; //targets speed in queen's direction
VECTORCH TargetDirection; //targets direction relative to queen
VECTORCH VectToTarget;
unsigned int PlayingHitDelta :1;
int SwerveTimer;
BOOL SwerveDirection;
VECTORCH ClimbStartPosition; //used when climing out of the airlock
BOOL AttackDoneItsDamage;
/*special hangar airlock state stuff*/
STRATEGYBLOCK* upper_airlockdoor_sbptr;
VECTORCH upper_airlockdoor_start;
STRATEGYBLOCK* lower_airlockdoor_sbptr;
VECTORCH lower_airlockdoor_start;
int soundHandle;
QUEEN_SOUND_CATEGORY lastSoundCategory;
} QUEEN_STATUS_BLOCK;
void InitQueenBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void QueenBehaviour(STRATEGYBLOCK *sbPtr);
void MakeQueenNear(STRATEGYBLOCK *sbPtr);
void MakeQueenFar(STRATEGYBLOCK *sbPtr);
void QueenIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple,SECTION_DATA *Section, VECTORCH *incoming, VECTORCH *point);
#ifdef __cplusplus
}
#endif
#endif

342
src/avp/bh_rubberduck.c Normal file
View file

@ -0,0 +1,342 @@
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
//#include "comp_shp.h"
#include "dynblock.h"
#include "dynamics.h"
//#include "lighting.h"
#include "pfarlocs.h"
#include "pvisible.h"
#include "load_shp.h"
#include "particle.h"
#include "bh_types.h"
#include "bh_RubberDuck.h"
#include "bh_weap.h"
#include "sfx.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
extern int NormalFrameTime;
void CreateRubberDuckBot(void)
{
CreateRubberDuck(&(Global_VDB_Ptr->VDB_World));
}
void CreateRubberDuck(VECTORCH *positionPtr)
{
STRATEGYBLOCK* sbPtr;
/* create and initialise a strategy block */
sbPtr = CreateActiveStrategyBlock();
if(!sbPtr) return; /* failure */
InitialiseSBValues(sbPtr);
sbPtr->I_SBtype = I_BehaviourRubberDuck;
AssignNewSBName(sbPtr);
/* create, initialise and attach a dynamics block */
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_GRENADE);
if(sbPtr->DynPtr)
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
EULER zeroEuler = {0,0,0};
zeroEuler.EulerY = FastRandom()&4095;
dynPtr->PrevPosition = dynPtr->Position = *positionPtr;
dynPtr->OrientEuler = zeroEuler;
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
dynPtr->LinVelocity.vx = 0;
dynPtr->LinVelocity.vy = 0;
dynPtr->LinVelocity.vz = 0;
dynPtr->LinImpulse.vy = 0;
dynPtr->GravityOn = 0;
dynPtr->Elasticity = 0;
dynPtr->IsFloating = 1;
}
else
{
/* dynamics block allocation failed... */
RemoveBehaviourStrategy(sbPtr);
return;
}
sbPtr->shapeIndex = GetLoadedShapeMSL("ciggies");//Duck");
sbPtr->maintainVisibility = 1;
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
LOCALASSERT(sbPtr->containingModule);
if(!(sbPtr->containingModule))
{
/* no containing module can be found... abort*/
RemoveBehaviourStrategy(sbPtr);
return;
}
}
void RubberDuckBehaviour(STRATEGYBLOCK *sbPtr)
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
int newLevel;
if (!sbPtr->SBdptr) return;
#if 1
newLevel = EffectOfRipples(&(dynPtr->Position));
{
int minusDeltaX,plusDeltaX,minusDeltaZ,plusDeltaZ;
VECTORCH delta;
delta.vx = dynPtr->Position.vx;
delta.vz = dynPtr->Position.vz;
delta.vx -= 50;
minusDeltaX = EffectOfRipples(&(delta))-newLevel;
delta.vx += 100;
plusDeltaX = EffectOfRipples(&(delta))-newLevel;
delta.vx -= 50;
delta.vz -= 50;
minusDeltaZ = EffectOfRipples(&(delta))-newLevel;
delta.vz += 100;
plusDeltaZ = EffectOfRipples(&(delta))-newLevel;
{
int scale = NormalFrameTime<<1;
if(scale>ONE_FIXED) scale = ONE_FIXED;
scale = ONE_FIXED;
dynPtr->LinImpulse.vx -= MUL_FIXED(scale,dynPtr->LinImpulse.vx);
dynPtr->LinImpulse.vz -= MUL_FIXED(scale,dynPtr->LinImpulse.vz);
}
if (minusDeltaX > plusDeltaX)
{
if (minusDeltaX>0) dynPtr->LinImpulse.vx = -minusDeltaX*256;
}
else
{
if (plusDeltaX>0) dynPtr->LinImpulse.vx = plusDeltaX*256;
}
if (minusDeltaZ > plusDeltaZ)
{
if (minusDeltaZ>0) dynPtr->LinImpulse.vz = -minusDeltaZ*256;
}
else
{
if (plusDeltaZ>0) dynPtr->LinImpulse.vz = plusDeltaZ*256;
}
}
dynPtr->LinImpulse.vy = 0;
{
int level = 0;
extern char LevelName[];
{
if (!strcmp(LevelName,"e3demosp")||!strcmp(LevelName,"e3demo"))
{
level = 3300;
}
else if (!strcmp(LevelName,"invasion_a"))
{
level = -35800;
}
else if (!strcmp(LevelName,"genshd1"))
{
level = 2656;
}
else if (!strcmp(LevelName,"fall")||!strcmp(LevelName,"fall_m"))
{
level = 12925;
}
else if (!strcmp(LevelName,"derelict"))
{
level = 32000;
}
dynPtr->Position.vy = newLevel+level;
}
}
dynPtr->AngVelocity.EulerY -= MUL_FIXED(dynPtr->AngVelocity.EulerY,NormalFrameTime);
dynPtr->AngVelocity.EulerY += (dynPtr->LinImpulse.vz + dynPtr->LinImpulse.vx+(FastRandom()&255)-128)/16;
dynPtr->AngVelocity.EulerZ = (dynPtr->LinImpulse.vz/256);
dynPtr->AngVelocity.EulerX = (dynPtr->LinImpulse.vx/256);
if (dynPtr->AngVelocity.EulerY > 8192) dynPtr->AngVelocity.EulerY = 8192;
else if (dynPtr->AngVelocity.EulerY < -8192) dynPtr->AngVelocity.EulerY = -8192;
DynamicallyRotateObject(dynPtr);
#else
{
VECTORCH dir;
dynPtr->GravityOn = 1;
dynPtr->IsFloating = 0;
dynPtr->CanClimbStairs = 0;
sbPtr->SBdptr->ObFlags3 |= ObFlag3_DynamicModuleObject;
if (BestDirectionOfTravel(&(Player->ObStrategyBlock->DynPtr->Position), &(dynPtr->Position), &dir))
{
dynPtr->LinVelocity.vx = MUL_FIXED(4000,dir.vx);
dynPtr->LinVelocity.vy = 0;
dynPtr->LinVelocity.vz = MUL_FIXED(4000,dir.vz);
}
else
{
dynPtr->LinVelocity.vx = 0;
dynPtr->LinVelocity.vy = 0;
dynPtr->LinVelocity.vz = 0;
}
}
#endif
}
extern void CreateFlamingDebris(VECTORCH *positionPtr, VECTORCH *dirPtr)
{
STRATEGYBLOCK* sbPtr;
/* create and initialise a strategy block */
sbPtr = CreateActiveStrategyBlock();
if(!sbPtr) return; /* failure */
InitialiseSBValues(sbPtr);
sbPtr->I_SBtype = I_BehaviourFragment;
AssignNewSBName(sbPtr);
sbPtr->SBdataptr = (void*)AllocateMem(sizeof(ONE_SHOT_BEHAV_BLOCK));
if (sbPtr->SBdataptr == 0)
{
// Failed to allocate a strategy block data pointer
RemoveBehaviourStrategy(sbPtr);
return;
}
((ONE_SHOT_BEHAV_BLOCK * ) sbPtr->SBdataptr)->counter = ((FastRandom()&32768)<<2) + 65535*2;
/* create, initialise and attach a dynamics block */
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ALIEN_DEBRIS);
if(sbPtr->DynPtr)
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
dynPtr->PrevPosition = dynPtr->Position = *positionPtr;
dynPtr->OrientEuler.EulerX = 0;
dynPtr->OrientEuler.EulerY = FastRandom()&4095;
dynPtr->OrientEuler.EulerZ = 0;
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
dynPtr->LinImpulse.vx = dirPtr->vx/4;
dynPtr->LinImpulse.vy = dirPtr->vy/4;
if (dynPtr->LinImpulse.vy>0) dynPtr->LinImpulse.vy=-dynPtr->LinImpulse.vy;
dynPtr->LinImpulse.vy += -4000;
dynPtr->LinImpulse.vz = dirPtr->vz/4;
dynPtr->AngVelocity.EulerX = (((FastRandom()&2047)-1023))<<2;
dynPtr->AngVelocity.EulerY = (((FastRandom()&2047)-1023))<<2;
dynPtr->AngVelocity.EulerZ = (((FastRandom()&2047)-1023))<<2;
dynPtr->Elasticity = ONE_FIXED/4;
}
else
{
/* dynamics block allocation failed... */
RemoveBehaviourStrategy(sbPtr);
return;
}
sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
sbPtr->maintainVisibility = 0;
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
LOCALASSERT(sbPtr->containingModule);
if(!(sbPtr->containingModule))
{
/* no containing module can be found... abort*/
RemoveBehaviourStrategy(sbPtr);
return;
}
{
MODULE tempModule;
DISPLAYBLOCK *dPtr;
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
VisibilityDefaultObjectMap.MapShape = sbPtr->shapeIndex;
tempModule.m_mapptr = &VisibilityDefaultObjectMap;
tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
tempModule.m_numlights = 0;
tempModule.m_lightarray = (struct lightblock *)0;
tempModule.m_extraitemdata = (struct extraitemdata *)0;
tempModule.m_dptr = NULL; /* this is important */
#if SupportWIndows95
tempModule.name = NULL; /* this is important */
#endif
AllocateModuleObject(&tempModule);
dPtr = tempModule.m_dptr;
if(dPtr==NULL)
{
RemoveBehaviourStrategy(sbPtr);
return;
}
sbPtr->SBdptr = dPtr;
dPtr->ObStrategyBlock = sbPtr;
dPtr->ObMyModule = NULL;
dPtr->ObWorld = dynPtr->Position;
dPtr->ObEuler = dynPtr->OrientEuler;
dPtr->ObMat = dynPtr->OrientMat;
/* make displayblock a dynamic module object */
dPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
sbPtr->SBDamageBlock.IsOnFire=1;
}
}
void CreateRubberDucks(void)
{
extern char LevelName[];
#if 0
if ( (!stricmp(LevelName,"e3demo")) || (!stricmp(LevelName,"e3demosp")) )
{
int i = 6;
do
{
VECTORCH pos = {1023,3400,27536};
pos.vx += (FastRandom()&4095)-2048;
pos.vz += (FastRandom()&4095)-2048;
CreateRubberDuck(&pos);
}
while(--i);
}
else
#endif
if ( (!stricmp(LevelName,"invasion_a")) )
{
int i = 6;
do
{
VECTORCH pos = {21803,-35491,40607};
pos.vx += FastRandom()&8191;
pos.vz -= FastRandom()&8191;
CreateRubberDuck(&pos);
}
while(--i);
}
}

6
src/avp/bh_rubberduck.h Normal file
View file

@ -0,0 +1,6 @@
extern void CreateRubberDuckBot(void);
extern void CreateRubberDuck(VECTORCH *positionPtr);
extern void CreateRubberDucks(void);
extern void RubberDuckBehaviour(STRATEGYBLOCK *sbPtr);
extern void CreateFlamingDebris(VECTORCH *positionPtr, VECTORCH *dirPtr);

151
src/avp/bh_selfdest.c Normal file
View file

@ -0,0 +1,151 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_selfdest.h"
#include "dynamics.h"
#include "weapons.h"
#include "particle.h"
#include "psnd.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern int NormalFrameTime;
void* SelfDestructBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
SELF_DESTRUCT_BEHAV_BLOCK* sd_bhv;
SELF_DESTRUCT_TOOLS_TEMPLATE* sd_tt;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
sd_bhv=(SELF_DESTRUCT_BEHAV_BLOCK*)AllocateMem(sizeof(SELF_DESTRUCT_BEHAV_BLOCK));
if(!sd_bhv)
{
memoryInitialisationFailure = 1;
return 0;
}
sd_bhv->bhvr_type=I_BehaviourSelfDestruct;
sd_tt=(SELF_DESTRUCT_TOOLS_TEMPLATE*)bhdata;
//copy stuff from tools template
COPY_NAME(sbptr->SBname, sd_tt->nameID);
sd_bhv->timer=sd_tt->timer;
sd_bhv->active=FALSE;
return (void*)sd_bhv;
}
void SelfDestructBehaveFun(STRATEGYBLOCK* sbptr)
{
SELF_DESTRUCT_BEHAV_BLOCK* sd_bhv;
GLOBALASSERT(sbptr);
sd_bhv = (SELF_DESTRUCT_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((sd_bhv->bhvr_type == I_BehaviourSelfDestruct));
if(sd_bhv->active)
{
sd_bhv->timer-=NormalFrameTime;
if(sd_bhv->timer<=0)
{
int i;
/* KJL 16:20:57 27/08/98 - let's do some pyrotechnics */
Sound_Play(SID_NICE_EXPLOSION,"d",&(Player->ObWorld));
MakeVolumetricExplosionAt(&Player->ObWorld,EXPLOSION_HUGE);
Player->ObStrategyBlock->SBDamageBlock.IsOnFire=1;
//blow up everone
for (i=0; i<NumActiveStBlocks; i++)
{
STRATEGYBLOCK *sbPtr = ActiveStBlockList[i];
if(sbPtr->I_SBtype==I_BehaviourAlien ||
sbPtr->I_SBtype==I_BehaviourQueenAlien ||
sbPtr->I_SBtype==I_BehaviourFaceHugger ||
sbPtr->I_SBtype==I_BehaviourPredator ||
sbPtr->I_SBtype==I_BehaviourXenoborg ||
sbPtr->I_SBtype==I_BehaviourMarine ||
sbPtr->I_SBtype==I_BehaviourSeal ||
sbPtr->I_SBtype==I_BehaviourPredatorAlien ||
sbPtr->I_SBtype==I_BehaviourAlien ||
sbPtr->I_SBtype==I_BehaviourMarinePlayer ||
sbPtr->I_SBtype==I_BehaviourPredatorPlayer ||
sbPtr->I_SBtype==I_BehaviourAlienPlayer)
{
{
//kill the creature/player
VECTORCH direction={0,-ONE_FIXED,0};
CauseDamageToObject(sbPtr,&certainDeath,ONE_FIXED,&direction);
}
}
}
sd_bhv->active = FALSE;
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct self_destruct_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
int timer; //in fixed point seconds
BOOL active;
}SELF_DESTRUCT_SAVE_BLOCK;
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV sd_bhv
void LoadStrategy_SelfDestruct(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
SELF_DESTRUCT_BEHAV_BLOCK* sd_bhv;
SELF_DESTRUCT_SAVE_BLOCK* block = (SELF_DESTRUCT_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourSelfDestruct) return;
sd_bhv = (SELF_DESTRUCT_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(timer);
COPYELEMENT_LOAD(active);
}
void SaveStrategy_SelfDestruct(STRATEGYBLOCK* sbPtr)
{
SELF_DESTRUCT_SAVE_BLOCK *block;
SELF_DESTRUCT_BEHAV_BLOCK* sd_bhv;
sd_bhv = (SELF_DESTRUCT_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(timer);
COPYELEMENT_SAVE(active);
}

38
src/avp/bh_selfdest.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef _bh_selfdest_h
#define _bh_selfdest_h 1
#ifdef __cplusplus
extern "C" {
#endif
extern void* SelfDestructBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void SelfDestructBehaveFun(STRATEGYBLOCK* sbptr);
typedef struct self_destruct_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
int timer; //in fixed point seconds
BOOL active;
}SELF_DESTRUCT_BEHAV_BLOCK;
typedef struct self_destruct_tools_template
{
char nameID[SB_NAME_LENGTH];
int timer;
}SELF_DESTRUCT_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

293
src/avp/bh_snds.c Normal file
View file

@ -0,0 +1,293 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_snds.h"
#include "dynblock.h"
#include "dynamics.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "dxlog.h"
#include "psndplat.h"
#include "jsndsup.h"
void * SoundBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr)
{
SOUND_BEHAV_BLOCK * sbb = 0;
SOUND_TOOLS_TEMPLATE * stt = (SOUND_TOOLS_TEMPLATE *)bhdata;
GLOBALASSERT (sbptr && stt);
sbb = (SOUND_BEHAV_BLOCK *)AllocateMem (sizeof (SOUND_BEHAV_BLOCK));
GLOBALASSERT (sbb);
sbb->sound_loaded = stt->sound_loaded;
sbb->position = stt->position;
sbb->inner_range = stt->inner_range;
sbb->outer_range = stt->outer_range;
sbb->max_volume = stt->max_volume;
sbb->pitch = stt->pitch;
sbb->sound_not_started = 1;
sbb->wav_name = (char *) AllocateMem (strlen (stt->sound_name) + 1);
strcpy (sbb->wav_name, stt->sound_name);
sbb->playing=stt->playing;
sbb->loop=stt->loop;
sbb->activ_no = SOUND_NOACTIVEINDEX;
return((void*)sbb);
}
void SoundBehaveDestroy (STRATEGYBLOCK * sbptr)
{
SOUND_BEHAV_BLOCK * sbb = (SOUND_BEHAV_BLOCK*)sbptr->SBdataptr;
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_Stop (sbb->activ_no);
}
if (sbb->wav_name)
{
DeallocateMem (sbb->wav_name);
}
}
void SoundBehaveFun (STRATEGYBLOCK * sbptr)
{
SOUND_BEHAV_BLOCK * sbb = (SOUND_BEHAV_BLOCK*)sbptr->SBdataptr;
if(!sbb->sound_loaded) return;
if (sbb->sound_not_started && Player)
{
SOUND3DDATA s3d;
if(sbb->playing)
{
//start playing the sound , but only if it is close enough
int dist=VectorDistance(&Player->ObWorld,&sbb->position);
if(dist<=sbb->outer_range)
{
s3d.position = sbb->position;
s3d.inner_range = sbb->inner_range;
s3d.outer_range = sbb->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
if(sbb->loop)
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "nelh", &s3d, &sbb->activ_no);
else
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "neh", &s3d, &sbb->activ_no);
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_ChangeVolume (sbb->activ_no, sbb->max_volume);
Sound_ChangePitch (sbb->activ_no, sbb->pitch);
}
}
}
sbb->sound_not_started = 0;
}
/* KJL 14:15:39 12/8/97 - kill any objects that are too far away */
if(sbb->playing)
{
int dist=VectorDistance(&Player->ObWorld,&sbb->position);
if(dist>sbb->outer_range)
{
//stop sound if it is playing
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_Stop (sbb->activ_no);
}
if(!sbb->loop && sbb->playing)
{
//not much point in restarting a non-looping sound, since it won't restart at the right place
sbb->playing=0;
}
return;
}
}
if (sbb->activ_no == SOUND_NOACTIVEINDEX && sbb->sound_loaded && sbb->playing)
{
if(sbb->loop)
{
SOUND3DDATA s3d;
s3d.position = sbb->position;
s3d.inner_range = sbb->inner_range;
s3d.outer_range = sbb->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
if(sbb->loop)
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "nelh", &s3d, &sbb->activ_no);
else
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "neh", &s3d, &sbb->activ_no);
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_ChangeVolume (sbb->activ_no, sbb->max_volume);
Sound_ChangePitch (sbb->activ_no, sbb->pitch);
}
}
else //sound has finished playing
{
sbb->playing=0;
}
}
// hack hack hack fixme fixme fix me
#pragma message ("Special code to deal with siren.wav!!");
if (AvP.DestructTimer != -1)
{
if (sbb->sound_loaded && sbb->activ_no != SOUND_NOACTIVEINDEX)
{
if (!_stricmp(GameSounds[sbb->sound_loaded->sound_num].wavName, "siren.wav"))
{
if (AvP.DestructTimer < ONE_FIXED * 10)
{
sbb->max_volume = 127;
}
else
{
sbb->max_volume = 90;
}
Sound_ChangeVolume (sbb->activ_no, sbb->max_volume);
}
}
}
}
void StartPlacedSoundPlaying(STRATEGYBLOCK* sbptr)
{
SOUND_BEHAV_BLOCK * sbb = 0;
GLOBALASSERT(sbptr);
GLOBALASSERT(sbptr->I_SBtype==I_BehaviourPlacedSound);
sbb = (SOUND_BEHAV_BLOCK*)sbptr->SBdataptr;
if(!sbb->sound_loaded) return;
if(!sbb->playing)
{
//if sound is within range start it
int dist=VectorDistance(&Player->ObWorld,&sbb->position);
if(dist<sbb->outer_range)
{
SOUND3DDATA s3d;
s3d.position = sbb->position;
s3d.inner_range = sbb->inner_range;
s3d.outer_range = sbb->outer_range;
s3d.velocity.vx = 0;
s3d.velocity.vy = 0;
s3d.velocity.vz = 0;
if(sbb->loop)
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "nelh", &s3d, &sbb->activ_no);
else
Sound_Play ((SOUNDINDEX)sbb->sound_loaded->sound_num, "neh", &s3d, &sbb->activ_no);
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_ChangeVolume (sbb->activ_no, sbb->max_volume);
Sound_ChangePitch (sbb->activ_no, sbb->pitch);
}
}
sbb->playing=1;
}
}
void StopPlacedSoundPlaying(STRATEGYBLOCK* sbptr)
{
SOUND_BEHAV_BLOCK * sbb = 0;
GLOBALASSERT(sbptr);
GLOBALASSERT(sbptr->I_SBtype==I_BehaviourPlacedSound);
sbb = (SOUND_BEHAV_BLOCK*)sbptr->SBdataptr;
if(!sbb->sound_loaded) return;
if(sbb->playing)
{
sbb->playing=0;
if (sbb->activ_no != SOUND_NOACTIVEINDEX)
{
Sound_Stop (sbb->activ_no);
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct placed_sound_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BOOL playing;
}PLACED_SOUND_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV sbb
void LoadStrategy_PlacedSound(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
SOUND_BEHAV_BLOCK * sbb;
PLACED_SOUND_SAVE_BLOCK* block = (PLACED_SOUND_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourPlacedSound) return;
sbb = (SOUND_BEHAV_BLOCK *)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(playing)
sbb->sound_not_started = 0;
Load_SoundState(&sbb->activ_no);
}
void SaveStrategy_PlacedSound(STRATEGYBLOCK* sbPtr)
{
PLACED_SOUND_SAVE_BLOCK* block;
SOUND_BEHAV_BLOCK * sbb;
sbb = (SOUND_BEHAV_BLOCK *)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(playing)
Save_SoundState(&sbb->activ_no);
}

73
src/avp/bh_snds.h Normal file
View file

@ -0,0 +1,73 @@
#ifndef _bh_snds_h
#define _bh_snds_h
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "jsndsup.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct sound_tools_template
{
VECTORCH position;
unsigned long inner_range;
unsigned long outer_range;
unsigned long max_volume;
unsigned long pitch;
unsigned int playing :1;
unsigned int loop :1;
char * sound_name;
LOADED_SOUND const * sound_loaded;
} SOUND_TOOLS_TEMPLATE;
typedef struct sound_behav_block
{
VECTORCH position;
unsigned long inner_range;
unsigned long outer_range;
int max_volume;
int pitch;
int activ_no;
char * wav_name;
// sound management stuff
LOADED_SOUND const * sound_loaded;
BOOL sound_not_started;
unsigned int playing :1;
unsigned int loop :1;
} SOUND_BEHAV_BLOCK;
void * SoundBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
void SoundBehaveFun (STRATEGYBLOCK * );
void SoundBehaveDestroy (STRATEGYBLOCK * sbptr);
void StartPlacedSoundPlaying(STRATEGYBLOCK* sbptr);
void StopPlacedSoundPlaying(STRATEGYBLOCK* sbptr);
#ifdef __cplusplus
}; // end of extern "c"
#endif
#endif

518
src/avp/bh_spcl.c Normal file
View file

@ -0,0 +1,518 @@
#include "3dc.h"
#include "bh_spcl.h"
#include "dynblock.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "vision.h"
#include "plat_shp.h"
extern int NormalFrameTime;
signed int RequestFadeToBlackLevel = 0;
extern DISPLAYBLOCK* Player;
void * InitXenoMorphRoom (void * bhdata, STRATEGYBLOCK * sbptr)
{
XENO_MORPH_ROOM_DATA * xmrd;
XENO_MORPH_ROOM_TOOLS_TEMPLATE * xmrtt;
MORPHCTRL* morphctrl;
MORPHHEADER* morphheader;
MORPHFRAME* morphframe;
MODULE * my_mod;
GLOBALASSERT(sbptr);
xmrd = (XENO_MORPH_ROOM_DATA *)AllocateMem(sizeof(XENO_MORPH_ROOM_DATA));
if (!xmrd)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
xmrd->bhvr_type = I_BehaviourXenoborgMorphRoom;
xmrtt = (XENO_MORPH_ROOM_TOOLS_TEMPLATE *)bhdata;
xmrd->MainShape = xmrtt->MainShape;
xmrd->ShutShape = xmrtt->ShutShape;
xmrd->WallsOutShape = xmrtt->WallsOutShape;
xmrd->ProbesInShape = xmrtt->ProbesInShape;
morphctrl = (MORPHCTRL*)AllocateMem(sizeof(MORPHCTRL));
if (!morphctrl)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphheader = (MORPHHEADER*)AllocateMem(sizeof(MORPHHEADER));
if (!morphheader)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphframe = (MORPHFRAME*)AllocateMem(sizeof(MORPHFRAME));
if (!morphframe)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
morphframe->mf_shape1 = xmrd->MainShape;
morphframe->mf_shape2 = xmrd->ShutShape;
morphheader->mph_numframes = 1;
morphheader->mph_maxframes = ONE_FIXED;
morphheader->mph_frames = morphframe;
morphctrl->ObMorphCurrFrame = 0;
morphctrl->ObMorphFlags = 0;
morphctrl->ObMorphSpeed = 0;
morphctrl->ObMorphHeader = morphheader;
// Copy the names over
COPY_NAME (sbptr->SBname, xmrtt->nameID);
COPY_NAME (xmrd->doorID, xmrtt->doorID);
// Setup module ref
ConvertModuleNameToPointer (&xmrtt->my_module, MainSceneArray[0]->sm_marray);
my_mod = xmrtt->my_module.mref_ptr;
GLOBALASSERT (my_mod);
my_mod->m_sbptr = sbptr;
sbptr->SBmoptr = my_mod;
sbptr->SBmomptr = my_mod->m_mapptr;
sbptr->SBflags.no_displayblock = 1;
sbptr->shapeIndex = my_mod->m_mapptr->MapShape;
xmrd->XMR_Mctrl = morphctrl;
xmrd->XMR_State = XMRS_Idle;
xmrd->DoorToRoom = 0;
sbptr->SBmorphctrl = xmrd->XMR_Mctrl;
sbptr->SBmorphctrl->ObMorphCurrFrame = 0;
if(sbptr->SBmomptr)
{
sbptr->SBmomptr->MapMorphHeader = sbptr->SBmorphctrl->ObMorphHeader;
}
// set up the animation control
#if SupportWindows95
{
int item_num;
TXACTRLBLK **pptxactrlblk;
int shape_num = my_mod->m_mapptr->MapShape;
SHAPEHEADER *shptr = GetShapeData(shape_num);
SetupPolygonFlagAccessForShape(shptr);
pptxactrlblk = &xmrd->tacb;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
int num_seq = 0;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if (pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = 0;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num);
while(pnew_txactrlblk->tac_txarray[num_seq+1])num_seq++;
/* set the flags in the animation header */
// we only ever have one frame of animation per sequence -
// nb this can change talk to richard - one sequence with two frames
// or mutliple sequences???
// pnew_txactrlblk->tac_txah.txa_flags |= txa_flag_play;
/* change the value held in pptxactrlblk
which point to the previous structures "next"
pointer*/
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else
{
memoryInitialisationFailure = 1;
}
}
}
*pptxactrlblk=0;
}
#endif
RequestFadeToBlackLevel = 0;
return((void*)xmrd);
}
extern MODULE * playerPherModule;
void XenoMorphRoomBehaviour (STRATEGYBLOCK * sbptr)
{
XENO_MORPH_ROOM_DATA * xmrd = (XENO_MORPH_ROOM_DATA *)sbptr->SBdataptr;
MORPHCTRL * mctrl = xmrd->XMR_Mctrl;
GLOBALASSERT (mctrl);
GLOBALASSERT (mctrl->ObMorphHeader);
GLOBALASSERT (mctrl->ObMorphHeader->mph_frames);
switch (xmrd->XMR_State)
{
case XMRS_Idle :
{
if (sbptr->SBmoptr->m_dptr)
{
if (playerPherModule == sbptr->SBmoptr)
{
VECTORCH diff;
diff.vx = Player->ObWorld.vx - sbptr->SBmoptr->m_dptr->ObWorld.vx;
diff.vy = Player->ObWorld.vy - sbptr->SBmoptr->m_dptr->ObWorld.vy;
diff.vz = Player->ObWorld.vz - sbptr->SBmoptr->m_dptr->ObWorld.vz;
if (diff.vx * diff.vx + diff.vz * diff.vz < 200000)
{
xmrd->XMR_State = XMRS_SafetyChecks;
}
}
}
break;
}
case XMRS_SafetyChecks :
{
BOOL can_continue = 1;
int i;
// waits to make sure everything is OK before it shuts the walls
if (xmrd->DoorToRoom)
{
PROXDOOR_BEHAV_BLOCK * doorbhv = (PROXDOOR_BEHAV_BLOCK*)xmrd->DoorToRoom->SBdataptr;
doorbhv->door_locked = 1;
if (doorbhv->door_state != I_door_closed)
{
can_continue = 0;
}
}
for (i=0; i<NumActiveStBlocks; i++)
{
if (ActiveStBlockList[i]->I_SBtype == I_BehaviourMarine || ActiveStBlockList[i]->I_SBtype == I_BehaviourSeal)
{
if (ActiveStBlockList[i]->containingModule == sbptr->SBmoptr)
{
can_continue = 0;
break;
}
}
}
if (sbptr->SBmoptr->m_dptr)
{
if (playerPherModule == sbptr->SBmoptr)
{
VECTORCH diff;
diff.vx = Player->ObWorld.vx - sbptr->SBmoptr->m_dptr->ObWorld.vx;
diff.vy = Player->ObWorld.vy - sbptr->SBmoptr->m_dptr->ObWorld.vy;
diff.vz = Player->ObWorld.vz - sbptr->SBmoptr->m_dptr->ObWorld.vz;
if (diff.vx * diff.vx + diff.vz * diff.vz > 200000)
{
can_continue = 0;
}
if (Player->ObStrategyBlock->DynPtr->Position.vx != Player->ObStrategyBlock->DynPtr->PrevPosition.vx)
{
can_continue = 0;
}
if (Player->ObStrategyBlock->DynPtr->Position.vy != Player->ObStrategyBlock->DynPtr->PrevPosition.vy)
{
can_continue = 0;
}
if (Player->ObStrategyBlock->DynPtr->Position.vz != Player->ObStrategyBlock->DynPtr->PrevPosition.vz)
{
can_continue = 0;
}
}
else
{
can_continue = 0;
}
}
else
{
can_continue = 0;
xmrd->XMR_State = XMRS_Idle;
}
if (can_continue)
{
// closes in player
mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->MainShape;
mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->ShutShape;
mctrl->ObMorphCurrFrame = 0;
mctrl->ObMorphFlags = mph_flag_play;
mctrl->ObMorphFlags |= mph_flag_noloop;
mctrl->ObMorphFlags &= ~mph_flag_reverse;
mctrl->ObMorphFlags &= ~mph_flag_finished;
mctrl->ObMorphSpeed = 1 << 18;
xmrd->XMR_State = XMRS_EnclosingPlayer;
}
break;
}
case XMRS_EnclosingPlayer :
{
UpdateMorphing(mctrl);
if(mctrl->ObMorphFlags & mph_flag_finished)
{
mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->ShutShape;
mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->WallsOutShape;
mctrl->ObMorphCurrFrame = 0;
mctrl->ObMorphFlags = mph_flag_play;
mctrl->ObMorphFlags |= mph_flag_noloop;
mctrl->ObMorphFlags &= ~mph_flag_reverse;
mctrl->ObMorphFlags &= ~mph_flag_finished;
mctrl->ObMorphSpeed = 1 << 13;
xmrd->XMR_State = XMRS_WallsOut;
}
break;
}
case XMRS_WallsOut :
{
UpdateMorphing(mctrl);
if(mctrl->ObMorphFlags & mph_flag_finished)
{
mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->WallsOutShape;
mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->ProbesInShape;
mctrl->ObMorphCurrFrame = 0;
mctrl->ObMorphFlags = mph_flag_play;
mctrl->ObMorphFlags |= mph_flag_noloop;
mctrl->ObMorphFlags &= ~mph_flag_reverse;
mctrl->ObMorphFlags &= ~mph_flag_finished;
mctrl->ObMorphSpeed = 1 << 13;
xmrd->XMR_State = XMRS_ProbesIn;
}
break;
}
case XMRS_ProbesIn :
{
UpdateMorphing(mctrl);
if(mctrl->ObMorphFlags & mph_flag_finished)
{
#if SupportWindows95
d3d_light_ctrl.ctrl = LCCM_CONSTCOLOUR;
d3d_light_ctrl.r = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.g = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.b = ONE_FIXED - RequestFadeToBlackLevel;
#endif
xmrd->XMR_State = XMRS_FadeToBlack;
}
break;
}
case XMRS_FadeToBlack :
{
RequestFadeToBlackLevel += (NormalFrameTime >> 1);
if (RequestFadeToBlackLevel > (ONE_FIXED))
{
RequestFadeToBlackLevel = ONE_FIXED;
xmrd->timer = 0;
xmrd->XMR_State = XMRS_Process;
}
#if SupportWindows95
d3d_light_ctrl.r = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.g = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.b = ONE_FIXED - RequestFadeToBlackLevel;
#endif
break;
}
case XMRS_Process :
{
xmrd->timer += NormalFrameTime;
if (xmrd->timer > (ONE_FIXED << 3))
{
if(sbptr->SBdptr)
{
SHAPEHEADER * pis = GetShapeData(xmrd->ProbesInShape);
SHAPEHEADER * ms = GetShapeData(xmrd->MainShape);
sbptr->SBdptr->ObMorphCtrl = 0;
xmrd->pis_items_str = pis->items;
xmrd->pis_sht_str = pis->sh_textures;
pis->items = ms->items;
pis->sh_textures = ms->sh_textures;
#if PSX
#else
pis->sh_instruction[4].sh_instr_data = ms->sh_instruction[4].sh_instr_data;
#endif
#if SupportWindows95
sbptr->SBdptr->ObTxAnimCtrlBlks = xmrd->tacb;
#endif
sbptr->SBdptr->ObShape = xmrd->ProbesInShape;
sbptr->SBdptr->ObShapeData = GetShapeData(xmrd->ProbesInShape);
// This moves the player to the required location
Player->ObStrategyBlock->DynPtr->Position = sbptr->SBdptr->ObWorld;
Player->ObStrategyBlock->DynPtr->Position.vy += 1472;
Player->ObStrategyBlock->DynPtr->Position.vx -= 900;
Player->ObStrategyBlock->DynPtr->PrevPosition = Player->ObStrategyBlock->DynPtr->Position;
Player->ObStrategyBlock->DynPtr->OrientEuler.EulerX = 0;
Player->ObStrategyBlock->DynPtr->OrientEuler.EulerY = 1024;
Player->ObStrategyBlock->DynPtr->OrientEuler.EulerZ = 0;
Player->ObStrategyBlock->DynPtr->PrevOrientEuler = Player->ObStrategyBlock->DynPtr->OrientEuler;
CreateEulerMatrix (&Player->ObStrategyBlock->DynPtr->OrientEuler,
&Player->ObStrategyBlock->DynPtr->OrientMat);
TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
Player->ObStrategyBlock->DynPtr->PrevOrientMat = Player->ObStrategyBlock->DynPtr->OrientMat;
xmrd->XMR_State = XMRS_Return;
}
}
break;
}
case XMRS_Return :
{
RequestFadeToBlackLevel -= (NormalFrameTime >> 1);
if (RequestFadeToBlackLevel <= 0)
{
RequestFadeToBlackLevel = 0;
xmrd->timer = 0;
xmrd->XMR_State = XMRS_ReleasePlayer;
#if SupportWindows95
d3d_light_ctrl.ctrl = LCCM_NORMAL;
#endif
}
#if SupportWindows95
d3d_light_ctrl.r = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.g = ONE_FIXED - RequestFadeToBlackLevel;
d3d_light_ctrl.b = ONE_FIXED - RequestFadeToBlackLevel;
#endif
break;
}
case XMRS_ReleasePlayer :
{
xmrd->timer += NormalFrameTime;
if (xmrd->timer > (ONE_FIXED << 2))
{
sbptr->SBdptr->ObShape = xmrd->MainShape;
sbptr->SBdptr->ObShapeData = GetShapeData(xmrd->MainShape);
sbptr->SBdptr->ObMorphCtrl = mctrl;
mctrl->ObMorphHeader->mph_frames->mf_shape1 = xmrd->ProbesInShape;
mctrl->ObMorphHeader->mph_frames->mf_shape2 = xmrd->MainShape;
mctrl->ObMorphCurrFrame = 0;
mctrl->ObMorphFlags = mph_flag_play;
mctrl->ObMorphFlags |= mph_flag_noloop;
mctrl->ObMorphFlags &= ~mph_flag_reverse;
mctrl->ObMorphFlags &= ~mph_flag_finished;
mctrl->ObMorphSpeed = 1 << 15;
xmrd->XMR_State = XMRS_Finished;
}
break;
}
case XMRS_Finished :
{
if(!(mctrl->ObMorphFlags & mph_flag_finished))
{
UpdateMorphing(mctrl);
}
else
{
SHAPEHEADER * pis = GetShapeData(xmrd->ProbesInShape);
#if SupportWindows95
sbptr->SBdptr->ObTxAnimCtrlBlks = 0;
#endif
pis->items = xmrd->pis_items_str;
pis->sh_textures = xmrd->pis_sht_str;
#if PSX
#else
pis->sh_instruction[4].sh_instr_data = xmrd->pis_items_str;
#endif
xmrd->XMR_State = XMRS_Idle;
}
break;
}
default :
GLOBALASSERT (0 == "Shouldn't be here");
break;
}
}

77
src/avp/bh_spcl.h Normal file
View file

@ -0,0 +1,77 @@
#ifndef _bh_spcl_h
#define _bh_spcl_h 1
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
void * InitXenoMorphRoom (void * bhdata, STRATEGYBLOCK * sbptr);
void XenoMorphRoomBehaviour (STRATEGYBLOCK * sbptr);
typedef struct xeno_morph_room_tools_template
{
int MainShape;
int ShutShape;
int WallsOutShape;
int ProbesInShape;
MREF my_module;
char nameID[SB_NAME_LENGTH];
char doorID[SB_NAME_LENGTH];
} XENO_MORPH_ROOM_TOOLS_TEMPLATE;
typedef enum xeno_morph_room_state
{
XMRS_Idle,
XMRS_SafetyChecks,
XMRS_EnclosingPlayer,
XMRS_WallsOut,
XMRS_ProbesIn,
XMRS_FadeToBlack,
XMRS_Process,
XMRS_Return,
XMRS_ReleasePlayer,
XMRS_Finished,
} XENO_MORPH_ROOM_STATE;
typedef struct xeno_morph_room_data
{
AVP_BEHAVIOUR_TYPE bhvr_type;
TXACTRLBLK *tacb;
MORPHCTRL *XMR_Mctrl;
XENO_MORPH_ROOM_STATE XMR_State;
int MainShape;
int ShutShape;
int WallsOutShape;
int ProbesInShape;
int timer;
#if PSX
struct polyheader ** pis_items_str;
struct psx_texture ** pis_sht_str;
#else
int ** pis_items_str;
int ** pis_sht_str;
#endif
char doorID[SB_NAME_LENGTH];
STRATEGYBLOCK* DoorToRoom;
} XENO_MORPH_ROOM_DATA;
#endif

350
src/avp/bh_swdor.c Normal file
View file

@ -0,0 +1,350 @@
/*------------------------------Patrick 12/3/97-----------------------------------
Source for Switch Operated Doors
--------------------------------------------------------------------------------*/
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "triggers.h"
#include "mslhand.h"
#include "psnd.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pvisible.h"
#include "bh_swdor.h"
#include "savegame.h"
/* external stuff */
extern int NormalFrameTime;
/*---------------------Patrick 12/3/97-------------------------
Initialisation of a switch door....
NB asumes that all switch doors start in a 'closed' state
-------------------------------------------------------------*/
void InitialiseSwitchDoor(void* bhdata, STRATEGYBLOCK* sbPtr)
{
SWITCH_DOOR_BEHAV_BLOCK *switchDoorBehaviourPtr;
SWITCH_DOOR_TOOLS_TEMPLATE *switchDoorToolsData;
MORPHCTRL *morphCtrl;
MORPHHEADER *morphHeader;
MORPHFRAME *morphFrame;
/* create a switch door data block */
switchDoorBehaviourPtr = (SWITCH_DOOR_BEHAV_BLOCK*)AllocateMem(sizeof(SWITCH_DOOR_BEHAV_BLOCK));
if (!switchDoorBehaviourPtr)
{
memoryInitialisationFailure = 1;
return;
}
switchDoorBehaviourPtr->myBehaviourType = I_BehaviourSwitchDoor;
sbPtr->SBdataptr = (void *)switchDoorBehaviourPtr;
/* cast the tools data for access */
switchDoorToolsData = (SWITCH_DOOR_TOOLS_TEMPLATE *)bhdata;
/* Set up a new Morph Control */
morphFrame = (MORPHFRAME*)AllocateMem(sizeof(MORPHFRAME));
if (!morphFrame)
{
memoryInitialisationFailure = 1;
return;
}
morphFrame->mf_shape1 = switchDoorToolsData->shapeOpen;
morphFrame->mf_shape2 = switchDoorToolsData->shapeClosed;
morphHeader = (MORPHHEADER*)AllocateMem(sizeof(MORPHHEADER));
if (!morphHeader)
{
memoryInitialisationFailure = 1;
return;
}
morphHeader->mph_numframes = 1;
morphHeader->mph_maxframes = ONE_FIXED;
morphHeader->mph_frames = morphFrame;
morphCtrl = (MORPHCTRL*)AllocateMem(sizeof(MORPHCTRL));
if (!morphCtrl)
{
memoryInitialisationFailure = 1;
return;
}
morphCtrl->ObMorphCurrFrame = 0;
morphCtrl->ObMorphFlags = 0;
morphCtrl->ObMorphSpeed = 0;
morphCtrl->ObMorphHeader = morphHeader;
switchDoorBehaviourPtr->morfControl = sbPtr->SBmorphctrl = morphCtrl;
/* set up my module, and it's morph controls */
COPY_NAME(sbPtr->SBname, switchDoorToolsData->nameID);
{
MREF mref=switchDoorToolsData->myModule;
ConvertModuleNameToPointer(&mref, MainSceneArray[0]->sm_marray);
GLOBALASSERT(mref.mref_ptr);
GLOBALASSERT(mref.mref_ptr->m_mapptr);
mref.mref_ptr->m_sbptr = sbPtr;
sbPtr->SBmoptr = mref.mref_ptr;
}
sbPtr->SBmomptr = sbPtr->SBmoptr->m_mapptr;
sbPtr->SBmomptr->MapMorphHeader = sbPtr->SBmorphctrl->ObMorphHeader;
sbPtr->SBmoptr->m_flags &= ~m_flag_open;
/* set up some other behaviour block stuff */
COPY_NAME(switchDoorBehaviourPtr->linkedDoorName, switchDoorToolsData->linkedDoorName);
switchDoorBehaviourPtr->doorState = I_door_closed;
switchDoorBehaviourPtr->linkedDoorPtr = (STRATEGYBLOCK *)0;
switchDoorBehaviourPtr->requestOpen = 0;
switchDoorBehaviourPtr->requestClose = 0;
switchDoorBehaviourPtr->openTimer = 0;
switchDoorBehaviourPtr->SoundHandle = SOUND_NOACTIVEINDEX;
CloseDoor(sbPtr->SBmorphctrl, DOOR_CLOSEFASTSPEED);
{
// Work out the door sound pitch
int maxX,maxY,maxZ,doorSize;
maxX=mainshapelist[morphFrame->mf_shape2]->shapemaxx;
maxY=mainshapelist[morphFrame->mf_shape2]->shapemaxy;
maxZ=mainshapelist[morphFrame->mf_shape2]->shapemaxz;
doorSize = maxX + maxY + maxZ;
if (doorSize < 3000) doorSize = 3000;
else if (doorSize > 8000) doorSize = 8000;
doorSize = (3000 - doorSize) >> 4;
switchDoorBehaviourPtr->doorType = doorSize;
}
}
/*---------------------Patrick 13/3/97-------------------------
Switch door behaviour function.
-------------------------------------------------------------*/
void SwitchDoorBehaviour(STRATEGYBLOCK* sbPtr)
{
SWITCH_DOOR_BEHAV_BLOCK *doorBehaviour;
MORPHCTRL *mCtrl;
MODULE *mPtr;
int linkedDoorIsClosed = 1;
GLOBALASSERT(sbPtr);
doorBehaviour = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
GLOBALASSERT(doorBehaviour);
mCtrl = doorBehaviour->morfControl;
GLOBALASSERT(mCtrl);
mPtr = sbPtr->SBmoptr;
GLOBALASSERT(mPtr);
/* update morphing.... */
UpdateMorphing(mCtrl);
/* get state of linked door: if there isn't a linked door, 'linkeddoorisclosed'
remains true so that there is no obstruction to operation of this door.
NB can't use 'GetState' here, as it returns true only if the door is fully open
(used by the NPC's). Here, we need to determine if the door is closed (which is
not the same as !open) */
if(doorBehaviour->linkedDoorPtr)
{
if(((SWITCH_DOOR_BEHAV_BLOCK *)doorBehaviour->linkedDoorPtr->SBdataptr)->doorState != I_door_closed) linkedDoorIsClosed = 0;
}
switch(doorBehaviour->doorState)
{
case I_door_opening:
{
/* LOCALASSERT(linkedDoorIsClosed); */
/* check if we've got a close request */
if(doorBehaviour->requestClose && !AnythingInMyModule(sbPtr->SBmoptr))
{
if(sbPtr->SBdptr) CloseDoor(mCtrl, DOOR_CLOSESLOWSPEED);
else CloseDoor(mCtrl, DOOR_CLOSEFASTSPEED);
doorBehaviour->doorState = I_door_closing;
}
/* already opening, so just allow the door to continue... */
else if(mCtrl->ObMorphFlags & mph_flag_finished)
{
//door has finished opening
doorBehaviour->doorState = I_door_open;
doorBehaviour->openTimer = DOOR_FAROPENTIME;
if (doorBehaviour->SoundHandle!=SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOOREND,"dp",&mPtr->m_world,doorBehaviour->doorType);
Sound_Stop(doorBehaviour->SoundHandle);
}
}
break;
}
case I_door_closing:
{
/* LOCALASSERT(linkedDoorIsClosed); */
/* check if we've got an open request, or anything has jumped in */
if((doorBehaviour->requestOpen)||(AnythingInMyModule(sbPtr->SBmoptr)))
{
//have to start opening again
if(sbPtr->SBdptr) OpenDoor(mCtrl, DOOR_OPENSLOWSPEED);
else OpenDoor(mCtrl, DOOR_OPENFASTSPEED);
doorBehaviour->doorState = I_door_opening;
Sound_Play(SID_DOORSTART,"dp",&mPtr->m_world,doorBehaviour->doorType);
Sound_Play(SID_DOORMID,"delp",&mPtr->m_world,&doorBehaviour->SoundHandle,doorBehaviour->doorType);
}
/* check if we've finished closing */
else if(mCtrl->ObMorphFlags & mph_flag_finished)
{
doorBehaviour->doorState = I_door_closed;
mPtr->m_flags &= ~m_flag_open;
if (doorBehaviour->SoundHandle!=SOUND_NOACTIVEINDEX)
{
Sound_Play(SID_DOOREND,"dp",&mPtr->m_world,doorBehaviour->doorType);
Sound_Stop(doorBehaviour->SoundHandle);
}
}
break;
}
case I_door_open:
{
/* LOCALASSERT(linkedDoorIsClosed); */
/*if we've got a close request , set the open timer to 0
so the door will start closing*/
if(doorBehaviour->requestClose)
{
doorBehaviour->openTimer=0;
}
/* check our timer to see if it's time to close*/
if(doorBehaviour->openTimer <= 0)
{
/* make sure there's nothing inside the door module before closing */
if(AnythingInMyModule(sbPtr->SBmoptr)==0)
{
if(sbPtr->SBdptr) CloseDoor(mCtrl, DOOR_CLOSESLOWSPEED);
else CloseDoor(mCtrl, DOOR_CLOSEFASTSPEED);
doorBehaviour->doorState = I_door_closing;
doorBehaviour->openTimer = 0;
Sound_Play(SID_DOORSTART,"dp",&mPtr->m_world,doorBehaviour->doorType);
Sound_Play(SID_DOORMID,"delp",&mPtr->m_world,&doorBehaviour->SoundHandle,doorBehaviour->doorType);
}
}
else doorBehaviour->openTimer -= NormalFrameTime;
break;
}
case I_door_closed:
{
if((doorBehaviour->requestOpen)&&(linkedDoorIsClosed))
{
/* just open the door */
if(sbPtr->SBdptr) OpenDoor(mCtrl, DOOR_OPENSLOWSPEED);
else OpenDoor(mCtrl, DOOR_OPENFASTSPEED);
doorBehaviour->doorState = I_door_opening;
mPtr->m_flags |= m_flag_open;
Sound_Play(SID_DOORSTART,"dp",&mPtr->m_world,doorBehaviour->doorType);
Sound_Play(SID_DOORMID,"delp",&mPtr->m_world,&doorBehaviour->SoundHandle,doorBehaviour->doorType);
}
}
}
/* must reset this every frame */
doorBehaviour->requestOpen = 0;
doorBehaviour->requestClose = 0;
}
/*--------------------**
** Loading and Saving **
**--------------------*/
typedef struct switch_door_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
DOOR_STATES doorState;
int openTimer;
unsigned int requestOpen :1;
unsigned int requestClose :1;
//from the morph control
int ObMorphCurrFrame;
int ObMorphFlags;
int ObMorphSpeed;
}SWITCH_DOOR_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV doorbhv
void LoadStrategy_SwitchDoor(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
SWITCH_DOOR_BEHAV_BLOCK *doorbhv;
SWITCH_DOOR_SAVE_BLOCK* block = (SWITCH_DOOR_SAVE_BLOCK*) header;
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourSwitchDoor) return;
doorbhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
COPYELEMENT_LOAD(doorState)
COPYELEMENT_LOAD(openTimer)
COPYELEMENT_LOAD(requestOpen)
COPYELEMENT_LOAD(requestClose)
COPYELEMENT_LOAD_EXT(block->ObMorphCurrFrame,doorbhv->morfControl->ObMorphCurrFrame)
COPYELEMENT_LOAD_EXT(block->ObMorphFlags , doorbhv->morfControl->ObMorphFlags)
COPYELEMENT_LOAD_EXT(block->ObMorphSpeed , doorbhv->morfControl->ObMorphSpeed)
Load_SoundState(&doorbhv->SoundHandle);
}
void SaveStrategy_SwitchDoor(STRATEGYBLOCK* sbPtr)
{
SWITCH_DOOR_SAVE_BLOCK *block;
SWITCH_DOOR_BEHAV_BLOCK *doorbhv ;
doorbhv = (SWITCH_DOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
COPYELEMENT_SAVE(doorState)
COPYELEMENT_SAVE(openTimer)
COPYELEMENT_SAVE(requestOpen)
COPYELEMENT_SAVE(requestClose)
COPYELEMENT_SAVE_EXT(block->ObMorphCurrFrame,doorbhv->morfControl->ObMorphCurrFrame)
COPYELEMENT_SAVE_EXT(block->ObMorphFlags , doorbhv->morfControl->ObMorphFlags)
COPYELEMENT_SAVE_EXT(block->ObMorphSpeed , doorbhv->morfControl->ObMorphSpeed)
Save_SoundState(&doorbhv->SoundHandle);
}

40
src/avp/bh_swdor.h Normal file
View file

@ -0,0 +1,40 @@
/*------------------------------Patrick 12/3/97-----------------------------------
Header for Switch Operated Doors
--------------------------------------------------------------------------------*/
typedef struct switch_door_behaviour_type
{
AVP_BEHAVIOUR_TYPE myBehaviourType; /* just for testing system integrity */
DOOR_STATES doorState;
MORPHCTRL *morfControl;
char linkedDoorName[SB_NAME_LENGTH];
STRATEGYBLOCK* linkedDoorPtr;
int openTimer;
unsigned int requestOpen :1;
unsigned int requestClose :1;
int SoundHandle;
int doorType; // Used to determine door sound type
} SWITCH_DOOR_BEHAV_BLOCK;
typedef struct switch_door_tools_template
{
BOOL state;
MREF myModule;
int shapeOpen;
int shapeClosed;
char linkedDoorName[SB_NAME_LENGTH];
char nameID[SB_NAME_LENGTH];
} SWITCH_DOOR_TOOLS_TEMPLATE;
#define DOOR_OPENSLOWSPEED (1<<16)
#define DOOR_OPENFASTSPEED (1<<20)
#define DOOR_CLOSESLOWSPEED (1<<17)
#define DOOR_CLOSEFASTSPEED (1<<20)
#define DOOR_FAROPENTIME (ONE_FIXED<<2) /* 4 seconds: DO NOT CHANGE THIS OR AI MAY NOT WORK*/
#define DOOR_OPENDISTANCE (5000) /* mm */
extern void InitialiseSwitchDoor(void* bhdata, STRATEGYBLOCK* sbptr);
extern void SwitchDoorBehaviour(STRATEGYBLOCK* sbptr);
extern void OpenDoor(MORPHCTRL *mctrl, int speed);
extern void CloseDoor(MORPHCTRL *mctrl, int speed);

591
src/avp/bh_track.c Normal file
View file

@ -0,0 +1,591 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "dynblock.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_track.h"
#include "dynamics.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "plat_shp.h"
#include "pvisible.h"
#include "bh_debri.h"
extern int RealFrameTime;
void NotifyTargetsForTrackPoint(TRACK_OBJECT_BEHAV_BLOCK* to_bhv,int point_num,int reversing);
void* TrackObjectBehaveInit(void* bhdata,STRATEGYBLOCK* sbptr)
{
TRACK_OBJECT_BEHAV_BLOCK* to_bhv;
TRACK_OBJECT_TOOLS_TEMPLATE* to_tt;
int i;
GLOBALASSERT(sbptr);
GLOBALASSERT(bhdata);
to_bhv=(TRACK_OBJECT_BEHAV_BLOCK*)AllocateMem(sizeof(TRACK_OBJECT_BEHAV_BLOCK));
if(!to_bhv)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
to_bhv->bhvr_type=I_BehaviourTrackObject;
to_tt=(TRACK_OBJECT_TOOLS_TEMPLATE*)bhdata;
sbptr->shapeIndex = to_tt->shape_num;
COPY_NAME(sbptr->SBname, to_tt->nameID);
GLOBALASSERT(to_tt->track);
to_bhv->to_track=to_tt->track;
to_bhv->to_track->sbptr=sbptr;
GLOBALASSERT(sbptr->DynPtr);
sbptr->DynPtr->Position = sbptr->DynPtr->PrevPosition = to_tt->position;
sbptr->DynPtr->OrientEuler = to_tt->orientation;
CreateEulerMatrix(&sbptr->DynPtr->OrientEuler, &sbptr->DynPtr->OrientMat);
TransposeMatrixCH(&sbptr->DynPtr->OrientMat);
/*check to see if object is animated.*/
{
TXACTRLBLK **pptxactrlblk;
int item_num;
SHAPEHEADER *shptr = GetShapeData(to_tt->shape_num);
pptxactrlblk = &to_bhv->to_tac;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
SetupPolygonFlagAccessForShape(shptr);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if(pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = 0;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(to_tt->shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, to_tt->shape_num);
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else *pptxactrlblk = NULL;
}
}
*pptxactrlblk=0;
}
to_bhv->request=track_no_request;
to_bhv->num_special_track_points=to_tt->num_special_track_points;
to_bhv->special_track_points=to_tt->special_track_points;
to_bhv->destruct_target_request=to_tt->destruct_target_request;
for(i=0;i<SB_NAME_LENGTH;i++)
{
to_bhv->destruct_target_ID[i]=to_tt->destruct_target_ID[i];
}
to_bhv->destruct_target_sbptr=0;
/* Initialise object's stats */
{
NPC_DATA *NpcData;
NpcData=GetThisNpcData(I_NPC_DefaultInanimate);
LOCALASSERT(NpcData);
sbptr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
sbptr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
sbptr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
}
sbptr->SBDamageBlock.Health*=to_tt->integrity;
if (to_tt->integrity > 20)
{
to_bhv->Indestructable = Yes;
sbptr->integrity = DEFAULT_OBJECT_INTEGRITY;
}
else if (to_tt->integrity < 1)
{
to_bhv->Indestructable = No;
sbptr->integrity = 1; // die immediately
}
else
{
to_bhv->Indestructable = No;
sbptr->integrity = (DEFAULT_OBJECT_INTEGRITY)*(to_tt->integrity);
}
Update_Track_Position_Only(to_bhv->to_track);
to_bhv->TimeUntilNetSynchAllowed=0;
return ((void*)to_bhv);
}
void NotifyTargetsForTrackPoint(TRACK_OBJECT_BEHAV_BLOCK* to_bhv,int point_num,int reversing)
{
int i;
GLOBALASSERT(to_bhv);
for(i=0;i<to_bhv->num_special_track_points;i++)
{
if(to_bhv->special_track_points[i].track_point_no==point_num)
{
SPECIAL_TRACK_POINT* stp=&to_bhv->special_track_points[i];
int j;
for(j=0;j<stp->num_targets;j++)
{
TRACK_POINT_TARGET* tpt=&stp->targets[j];
if(reversing)
{
if(tpt->flags & TrackRequestFlag_ActiveBackward)
{
if(tpt->flags & TrackRequestFlag_OppositeBackward)
{
RequestState(tpt->target_sbptr,!tpt->request,0);
}
else
{
RequestState(tpt->target_sbptr,tpt->request,0);
}
}
}
else
{
if(tpt->flags & TrackRequestFlag_ActiveForward)
{
RequestState(tpt->target_sbptr,tpt->request,0);
}
}
}
break;
}
}
}
void TrackObjectBehaveFun(STRATEGYBLOCK* sbptr)
{
TRACK_OBJECT_BEHAV_BLOCK *to_bhv;
TRACK_CONTROLLER* track;
int current_section;
int reversing;
GLOBALASSERT(sbptr);
to_bhv = (TRACK_OBJECT_BEHAV_BLOCK*)sbptr->SBdataptr;
GLOBALASSERT((to_bhv->bhvr_type == I_BehaviourTrackObject));
GLOBALASSERT(to_bhv->to_track);
track=to_bhv->to_track;
//update texture animation if object has one
if(to_bhv->to_tac)
{
DISPLAYBLOCK* dptr = sbptr->SBdptr;
if(dptr)
{
if(!dptr->ObTxAnimCtrlBlks)
{
dptr->ObTxAnimCtrlBlks = to_bhv->to_tac;
}
}
}
//check to see if any request have come through.
if(AvP.Network != I_No_Network)
{
if(to_bhv->request == track_no_request)
{
to_bhv->TimeUntilNetSynchAllowed-=RealFrameTime;
if(to_bhv->TimeUntilNetSynchAllowed<0)
{
to_bhv->TimeUntilNetSynchAllowed=0;
}
}
else
{
to_bhv->TimeUntilNetSynchAllowed=5*ONE_FIXED;
}
}
switch(to_bhv->request)
{
case track_request_start :
{
Start_Track_Playing(track);
to_bhv->request=track_no_request;
}
break;
case track_request_startforward :
{
track->reverse=0;
Start_Track_Playing(track);
to_bhv->request=track_no_request;
}
break;
case track_request_startbackward :
{
track->reverse=1;
Start_Track_Playing(track);
to_bhv->request=track_no_request;
}
break;
case track_request_stop :
{
Stop_Track_Playing(track);
to_bhv->request=track_no_request;
}
break;
}
if(!track->playing) return;
current_section=track->current_section;
reversing=track->reverse;
Update_Track_Position(track);
if(to_bhv->special_track_points)
{
//see which track points the track has gone through, and notify the
//targets for those points
/*
if(reversing)
{
while(current_section!=track->current_section)
{
NotifyTargetsForTrackPoint(to_bhv,current_section,1);
current_section--;
if(current_section<0)
{
//looped to end , so passed last point
current_section=track->num_sections-1;
NotifyTargetsForTrackPoint(to_bhv,track->num_sections,1);
}
}
if(current_section==0 && !track->playing)
{
//stopped at start , so passed point 0
NotifyTargetsForTrackPoint(to_bhv,0,1);
}
}
else
{
while(current_section!=track->current_section)
{
NotifyTargetsForTrackPoint(to_bhv,current_section+1,0);
current_section++;
if(current_section>=track->num_sections)
{
//looped to start , so passed first point
current_section=0;
NotifyTargetsForTrackPoint(to_bhv,0,0);
}
}
if(current_section==(track->num_sections-1) && !track->playing)
{
//stopped at end , so passed last point
NotifyTargetsForTrackPoint(to_bhv,track->num_sections,0);
}
}
*/
while(reversing!=track->reverse || current_section!=track->current_section)
{
if(reversing)
{
NotifyTargetsForTrackPoint(to_bhv,current_section,1);
current_section--;
if(current_section<0)
{
if(track->loop)
{
//looped to end , so passed last point
current_section=track->num_sections-1;
NotifyTargetsForTrackPoint(to_bhv,track->num_sections,1);
}
else
{
current_section=0;
reversing=0;
}
}
}
else
{
NotifyTargetsForTrackPoint(to_bhv,current_section+1,0);
current_section++;
if(current_section>=track->num_sections)
{
if(track->loop)
{
//looped to start , so passed first point
current_section=0;
NotifyTargetsForTrackPoint(to_bhv,0,0);
}
else
{
current_section=track->num_sections-1;
reversing=1;
}
}
}
}
if(!track->playing)
{
if(track->reverse)
{
//stopped at end , so passed last point
NotifyTargetsForTrackPoint(to_bhv,track->num_sections,0);
}
else
{
//stopped at start , so passed point 0
NotifyTargetsForTrackPoint(to_bhv,0,1);
}
}
}
}
void TrackObjectIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple)
{
TRACK_OBJECT_BEHAV_BLOCK* to_bhv = sbPtr->SBdataptr;
LOCALASSERT(to_bhv);
#if 0
if((AvP.Network==I_Peer)&&(!InanimateDamageFromNetHost))
{
//add track damaged net message
return;
}
else if(AvP.Network==I_Host)
{
//add track damaged net message
//if(sbPtr->SBDamageBlock.Health <= 0) AddNetMsg_InanimateObjectDestroyed(sbPtr);
}
#endif
if(AvP.Network != I_No_Network)
{
//I don't want to consider destructable track objects in net games for the moment
//would screw up the strategy synching
return;
}
if (!to_bhv->Indestructable)
{
if(sbPtr->SBDamageBlock.Health <= 0)
{
//notify target of destruction
if(to_bhv->destruct_target_sbptr)
{
RequestState(to_bhv->destruct_target_sbptr,to_bhv->destruct_target_request,0);
}
MakeFragments(sbPtr);
DestroyAnyStrategyBlock(sbPtr);
}
}
}
#define TRACKSYNCH_ON_FORWARD 0
#define TRACKSYNCH_OFF_FORWARD 1
#define TRACKSYNCH_ON_REVERSE 2
#define TRACKSYNCH_OFF_REVERSE 3
int TrackObjectGetSynchData(STRATEGYBLOCK* sbPtr)
{
TRACK_OBJECT_BEHAV_BLOCK* to_bhv = sbPtr->SBdataptr;
LOCALASSERT(to_bhv);
if(to_bhv->to_track->playing)
{
if(to_bhv->to_track->reverse)
return TRACKSYNCH_ON_REVERSE;
else
return TRACKSYNCH_ON_FORWARD;
}
else
{
if(to_bhv->to_track->reverse)
return TRACKSYNCH_OFF_REVERSE;
else
return TRACKSYNCH_OFF_FORWARD;
}
}
void TrackObjectSetSynchData(STRATEGYBLOCK* sbPtr,int status)
{
TRACK_OBJECT_BEHAV_BLOCK* to_bhv = sbPtr->SBdataptr;
LOCALASSERT(to_bhv);
if(to_bhv->TimeUntilNetSynchAllowed>0)
{
//ignore this attempt to synch the switch
return;
}
if(to_bhv->to_track->playing)
{
//don't bother stopping moving tracks;
return;
}
switch(status)
{
case TRACKSYNCH_ON_FORWARD :
to_bhv->request=track_request_startforward;
break;
case TRACKSYNCH_OFF_FORWARD :
if(to_bhv->to_track->reverse && !to_bhv->to_track->loop)
{
//track is at the end , but should be at the start
to_bhv->request=track_request_startbackward;
}
break;
case TRACKSYNCH_ON_REVERSE :
to_bhv->request=track_request_startbackward;
break;
case TRACKSYNCH_OFF_REVERSE :
if(!to_bhv->to_track->reverse && !to_bhv->to_track->loop)
{
//track is at the start , but should be at the end
to_bhv->request=track_request_startforward;
}
break;
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct track_object_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BOOL Indestructable;
TRACK_OBJECT_REQUEST_STATE request;
//strategyblock stuff
int integrity;
DAMAGEBLOCK SBDamageBlock;
}TRACK_OBJECT_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV to_bhv
void LoadStrategy_TrackObject(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
TRACK_OBJECT_BEHAV_BLOCK *to_bhv;
TRACK_OBJECT_SAVE_BLOCK* block = (TRACK_OBJECT_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourTrackObject) return;
to_bhv = (TRACK_OBJECT_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
COPYELEMENT_LOAD(Indestructable)
COPYELEMENT_LOAD(request)
sbPtr->integrity = block->integrity;
sbPtr->SBDamageBlock = block->SBDamageBlock;
//load the track position
if(to_bhv->to_track)
{
SAVE_BLOCK_HEADER* track_header = GetNextBlockIfOfType(SaveBlock_Track);
if(track_header)
{
LoadTrackPosition(track_header,to_bhv->to_track);
}
}
}
void SaveStrategy_TrackObject(STRATEGYBLOCK* sbPtr)
{
TRACK_OBJECT_SAVE_BLOCK* block;
TRACK_OBJECT_BEHAV_BLOCK *to_bhv;
to_bhv = (TRACK_OBJECT_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
COPYELEMENT_SAVE(Indestructable)
COPYELEMENT_SAVE(request)
block->integrity = sbPtr->integrity;
block->SBDamageBlock = sbPtr->SBDamageBlock;
//save the track position
if(to_bhv->to_track)
{
SaveTrackPosition(to_bhv->to_track);
}
}

104
src/avp/bh_track.h Normal file
View file

@ -0,0 +1,104 @@
#ifndef _bh_track_h_
#define _bh_track_h_ 1
#include "track.h"
#ifdef __cplusplus
extern "C" {
#endif
extern void* TrackObjectBehaveInit(void* bhdata, STRATEGYBLOCK* sbptr);
extern void TrackObjectBehaveFun(STRATEGYBLOCK* sbptr);
extern void TrackObjectIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple);
extern int TrackObjectGetSynchData(STRATEGYBLOCK* sbptr);
extern void TrackObjectSetSynchData(STRATEGYBLOCK* sbptr,int status);
typedef enum track_object_req_states
{
track_no_request,
track_request_start,
track_request_stop,
track_request_startforward,
track_request_startbackward,
}TRACK_OBJECT_REQUEST_STATE;
#ifndef TrackRequestFlag_ActiveForward
#define TrackRequestFlag_ActiveForward 0x00000001
#define TrackRequestFlag_ActiveBackward 0x00000002
#define TrackRequestFlag_OppositeBackward 0x00000004
#endif
typedef struct track_point_target
{
char target_name [SB_NAME_LENGTH];
STRATEGYBLOCK * target_sbptr;
int request;
int flags;
}TRACK_POINT_TARGET;
typedef struct special_track_point
{
int track_point_no;
int num_targets;
TRACK_POINT_TARGET* targets;
}SPECIAL_TRACK_POINT;
typedef struct track_object_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
BOOL Indestructable;
TRACK_CONTROLLER* to_track;
TRACK_OBJECT_REQUEST_STATE request;
TXACTRLBLK *to_tac;//for objects with anims on them
int num_special_track_points;
SPECIAL_TRACK_POINT* special_track_points;
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* destruct_target_sbptr;
int TimeUntilNetSynchAllowed;
}TRACK_OBJECT_BEHAV_BLOCK;
typedef struct track_object_tools_template
{
char nameID[SB_NAME_LENGTH];
int shape_num;
TRACK_CONTROLLER* track;
VECTORCH position;
EULER orientation;
int num_special_track_points;
SPECIAL_TRACK_POINT* special_track_points;
int integrity; // 0-20 (>20 = indestructable)
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
}TRACK_OBJECT_TOOLS_TEMPLATE;
#ifdef __cplusplus
};
#endif
#endif

3723
src/avp/bh_types.c Normal file

File diff suppressed because it is too large Load diff

516
src/avp/bh_types.h Normal file
View file

@ -0,0 +1,516 @@
#ifndef _bhtypes_h_
#define _bhtypes_h_ 1
#ifndef _equipmnt_h_
#include "equipmnt.h"
#endif
#include "gameflow.h"
#include "pmove.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
I think I am going to devide the behaviour of objects into two different forms
In terms of emulating 3d we need to think of multiple cluster of sprite sequences to
descibe any one motion. In this respect I am going to have a list of capabilities for
objects. If you supply One animation sequence that allows a capabiltity the animation capability
language will allow that capabiltiy. If it is a front walk, the object will walk
but it will always display the one type of sequence even if it is walking away from
you. When we load up a sprite sequence we include an enum that tells us what capabiltiy_type
these sequence is part of. The animation capabiltity language and capabiltiy_type can refer
to morphing equally as to sprites (morphing is some what easier as the object will always look
right
Other objects are rather dull and the above capability system is too complex. A module
playing a TV does not need such a comple behaviour. These objects have much simpler
strategies and we will have specfifc low level functions to deal with them.
*/
typedef enum actor_capability_types
{
BHTypeWalk, /* gen movement */
BHTypeCrawl, /* gen movement */
BHTypeRun, /* gen movement */
BHTypeFly, /* gen movement */
BHTypeStandUp,
BHTypeSitDown,
BHTypeKneelDown,
BHTypeCroach,
BHTypeAttack1,
BHTypeAttack2,
BHTypeAttack3,
BHTypeRangedAttack1,
BHTypeRangedAttack2,
BHTypeRangedAttack3,
BHTypeHit,
BHTypeDying,
BHTypeDead,
BHTypeJump
} ACTOR_CAPABILITY_TYPES;
/* ****************** STRATEGY BLOCK Behaviour DESCRIPTION ************ */
typedef struct CapabilityDescription
{
int num_animating_items;
int **item_animations;
} CAPABILITY_DESCRIPTION;
/* the item_animations are specific to each animating
item the have no formal description interms of a type
the theyare listed as.
int item_num
seq_des1
seq_des2
seq_des3
seq_des4
term
the list of void* pointers points to the initial
item_num for the following sequences
*/
typedef struct sequence_descriptor
{
ACTOR_CAPABILITY_TYPES cap_type;
TXANIMHEADER* txanim_header;
int view_angle;
int view_azimuth;
} SEQUENCE_DESCRIPTOR;
typedef struct SuicideTimer
{
int time_left; /*agrgggghhh*****/
}SUICIDE_TIMER;
/**************************** SPECIFIC BEHAVIOUR TYPES ************************/
// ENUM now in Stratdef.h
/*-------------Patrick 21/10/96 --------------------
This structure is used in Player Status to represent
the various player input requests. It consists
of single bit fields, which are used as a bit-mask
for recording key-combo sequences for special moves.
for the purposes of bit-masking, it is implemented as
a union with an unsigned int...
NB it is easier to add new fields towards the end,
as otherwise you may have to change the special
move input bitmasks
--------------------------------------------------*/
typedef struct player_input_requests
{
unsigned int Rqst_Forward :1;
unsigned int Rqst_Backward :1;
unsigned int Rqst_TurnLeft :1;
unsigned int Rqst_TurnRight :1;
unsigned int Rqst_LookUp :1;
unsigned int Rqst_LookDown :1;
unsigned int Rqst_FirePrimaryWeapon :1;
unsigned int Rqst_Faster :1;
unsigned int Rqst_SideStepLeft :1;
unsigned int Rqst_SideStepRight :1;
unsigned int Rqst_Strafe :1;
unsigned int Rqst_Crouch :1;
unsigned int Rqst_Jump :1;
/* NB Lie Down is set by special moves only (ie doesn't require a user input, configuration entry, etc) */
unsigned int Rqst_Operate :1;
unsigned int Rqst_CentreView :1;
unsigned int Rqst_NextWeapon :1;
unsigned int Rqst_PreviousWeapon :1;
unsigned int Rqst_WeaponNo :4;
unsigned int Rqst_QuitGame :1;
unsigned int Rqst_PauseGame :1;
/* KJL 16:58:37 04/11/98 - Change vision does a variety of things, dependent on the player's
character. */
unsigned int Rqst_ChangeVision :1;
unsigned int Rqst_FireSecondaryWeapon :1;
/* Predator Specific */
unsigned int Rqst_CycleVisionMode :1;
unsigned int Rqst_ZoomIn :1;
unsigned int Rqst_ZoomOut :1;
unsigned int Rqst_GrapplingHook :1;
/* Alien Specific */
unsigned int Rqst_Spit :1;
/* Marine Specific */
unsigned int Rqst_ThrowFlare :1;
unsigned int Rqst_Jetpack :1;
unsigned int :0;
}PLAYER_INPUT_REQUESTS;
/*-------------Patrick 23/10/96 --------------------
Some defines for key combo bit masks
these should correspond to the above request flags.
--------------------------------------------------*/
#define INPUT_BITMASK_FORWARD 0x00000001
#define INPUT_BITMASK_BACKWARD 0x00000002
#define INPUT_BITMASK_LEFT 0x00000004
#define INPUT_BITMASK_RIGHT 0x00000008
#define INPUT_BITMASK_FIRE 0x00000040
#define INPUT_BITMASK_FASTER 0x00000080
#define INPUT_BITMASK_STRAFE 0x00000100
#define INPUT_BITMASK_CROUCH 0x00000200
#define INPUT_BITMASK_JUMP 0x00000400
/* KJL 14:16:52 09/20/96 - the new player status type
modified by patrick */
typedef struct player_status
{
AVP_BEHAVIOUR_TYPE bhvr_type;
/* player's weapons */
PLAYER_WEAPON_DATA WeaponSlot[MAX_NO_OF_WEAPON_SLOTS];
enum WEAPON_SLOT SelectedWeaponSlot;
enum WEAPON_SLOT SwapToWeaponSlot;
enum WEAPON_SLOT PreviouslySelectedWeaponSlot;
int Health; /* in 16.16 */
int Energy; /* in 16.16 */
int Armour; /* in 16.16 */
/* general info */
/* KJL 17:28:20 09/19/96 - not yet used
int ArmourType;
int HealingRate;
int CloakingType;
int VisionType;
*/
/*-----Patrick 15/10/96---------
Player movement bits...
------------------------------*/
enum player_morph_state ShapeState; /* for controlling morphing */
/* and these are for free (ie normal) movement,
and should be set by the (platform dependant) input
device reading function */
unsigned char Mvt_DeviceType;
signed int Mvt_MotionIncrement; /* 65536 (Forward) to -65536 (Backward) */
signed int Mvt_TurnIncrement; /* 65536 (Right) to -65536 (Left)*/
signed int Mvt_PitchIncrement; /* 65536 to -65536 */
signed int Mvt_SideStepIncrement; /* 65536 to -65536 */
/* KJL 10:48:33 03/26/97 - inertia data */
signed int ForwardInertia;
signed int StrafeInertia;
signed int TurnInertia;
int ViewPanX; /* the looking up/down value that used to be in displayblock */
union Mvt_InputRequests
{
unsigned int Mask;
unsigned int Mask2;
PLAYER_INPUT_REQUESTS Flags;
}Mvt_InputRequests;
/* security clearances */
unsigned int securityClearances;
/* useful flags */
unsigned int IsAlive :1;
unsigned int IsImmortal :1;
unsigned int Mvt_AnalogueTurning :1;
unsigned int Mvt_AnaloguePitching :1;
unsigned int Absolute_Pitching :1;
unsigned int SwappingIsDebounced :1;
unsigned int DemoMode :1;
unsigned int IHaveAPlacedAutogun :1;
unsigned int IsMovingInWater :1;
unsigned int JetpackEnabled :1;
unsigned int GrapplingHookEnabled :1;
unsigned int MTrackerType;
/* Patrick: 1/7/97 : for predator-type cloaking stuff */
unsigned int cloakOn :1;
unsigned int cloakPositionGivenAway :1;
int FieldCharge;
int cloakPositionGivenAwayTimer;
int PlasmaCasterCharge;
/* KJL 99/2/3 - Cloaking Effectiveness
ranges from 0 (useless) to ONE_FIXED (practically invisible) */
int CloakingEffectiveness;
// John 28/7/97 Game Flow stuff
PLAYERMISSION CurrentMission;
unsigned long StateChangeObjectFlags;
/* Encumberance */
ENCUMBERANCE_STATE Encumberance;
STRATEGYBLOCK *MyFaceHugger;
STRATEGYBLOCK *MyCorpse;
int tauntTimer;
int soundHandle;
/* Why no 2, you ask? */
int soundHandle3;
/* Because '3' is always crackling fire, for *
* netghosts and corpses. Really, 2 should be*
* the voice and 1 should be weapon use. */
int soundHandle4;
/* For the splash. */
int soundHandle5;
/* For the jetpack. */
int soundHandleForPredatorCloakDamaged;
/* the above seemed better than soundHandle5 :) */
HMODELCONTROLLER HModelController;
int incidentFlag;
int incidentTimer;
int fireTimer;
int invulnerabilityTimer;
} PLAYER_STATUS;
#define TAUNT_LENGTH (ONE_FIXED<<1)
#define PLAYER_ON_FIRE_TIME (ONE_FIXED*20)
#define STARTOFGAME_MARINE_HEALTH (100*65536) /* ie. 100 in 16.16 notation */
#define STARTOFGAME_MARINE_ENERGY (100*65536) /* ie. 100 in 16.16 notation */
#define STARTOFGAME_MARINE_ARMOUR (100*65536) /* ie. 100 in 16.16 notation */
/* Patrick 22/8/97------------------------------------------------
Cloaking stuff
------------------------------------------------------------------*/
#define PLAYERCLOAK_MAXENERGY (30*ONE_FIXED) /* fixed point seconds */
#define PLAYERCLOAK_RECHARGEFACTOR (4) /* ... times slower than discharge */
#define PLAYERCLOAK_POSTIONGIVENAWAYTIME (ONE_FIXED>>2) /*(2*ONE_FIXED) fixed point seconds */
#define PLAYERCLOAK_THRESHOLD (5*ONE_FIXED)
#define PLAYERCLOAK_POWERON_DRAIN (2*ONE_FIXED)
#define PLAYERCLOAK_DRAIN_FACTOR (4)
/* Moved mere from player.c, CDF 23/4/98 */
extern PLAYER_STATUS* PlayerStatusPtr;
/******************** SIMPLE ANIMATIONS ********************/
typedef struct simpleanimbehaviour
{
AVP_BEHAVIOUR_TYPE bhvr_type;
TXACTRLBLK *tacbSimple;
}SIMPLE_ANIM_BEHAV_BLOCK;
typedef struct simple_anim_tools_template
{
int shape_num;
MREF my_module;
char nameID[SB_NAME_LENGTH];
} SIMPLE_ANIM_TOOLS_TEMPLATE;
/**********************************************************/
/**********************DOORS*******************************/
typedef enum{ /* this may be flags*/
I_door_opening,
I_door_closing,
I_door_open,
I_door_closed,
} DOOR_STATES;
/******************** PROXIMITY DOORS ********************/
typedef struct ProxDoorBehaviourType
{
AVP_BEHAVIOUR_TYPE bhvr_type;
int door_state;
MORPHCTRL *PDmctrl;
/*---- Patrick 1/1/97 -----
added for far ai stratgies
--------------------------*/
int alienTimer;
unsigned int alienTrigger :1;
unsigned int marineTrigger :1;
unsigned int triggeredByMarine :1;
/*---- Roxby 1/1/97 -----
Added so that another door can lock
this door closed
--------------------------*/
BOOL lockable_door;
BOOL door_locked;
char target_name[SB_NAME_LENGTH];
STRATEGYBLOCK* door_lock_target;
int SoundHandle;
int doorType; // Used to determine door sound type
int door_opening_speed;
int door_closing_speed;
} PROXDOOR_BEHAV_BLOCK;
typedef struct prox_door_tools_template
{
BOOL has_lock_target;
char target_name [SB_NAME_LENGTH];
MREF my_module;
int shape_open;
int shape_closed;
char nameID[SB_NAME_LENGTH];
BOOL door_is_locked;
int door_opening_speed;
int door_closing_speed;
} PROX_DOOR_TOOLS_TEMPLATE;
/* Structures for Stat Initialisation */
typedef enum {
I_NPC_Civilian=0,
I_NPC_FaceHugger,
I_NPC_ChestBurster,
I_NPC_Alien,
I_NPC_Xenoborg,
I_NPC_Marine,
I_NPC_PredatorAlien,
I_NPC_SFMarine,
I_NPC_Predator,
I_NPC_PraetorianGuard,
I_NPC_AlienQueen,
I_NPC_DefaultInanimate,
I_PC_Alien_Easy,
I_PC_Marine_Easy,
I_PC_Predator_Easy,
I_PC_Alien_Medium,
I_PC_Marine_Medium,
I_PC_Predator_Medium,
I_PC_Alien_Hard,
I_PC_Marine_Hard,
I_PC_Predator_Hard,
I_PC_Alien_Impossible,
I_PC_Marine_Impossible,
I_PC_Predator_Impossible,
I_PC_Alien_MaxStats,
I_NPC_SentryGun,
I_NPC_Android,
I_NPC_End,
} NPC_TYPES;
typedef struct {
NPC_TYPES Type;
//int StartingHealth;
//int StartingArmour;
//SBHEALTHFLAGS SB_H_flags;
DAMAGEBLOCK StartingStats;
} NPC_DATA;
/* Interface function! */
extern NPC_DATA *GetThisNpcData(NPC_TYPES NpcType);
/********************************************************/
/******************* Database behaviour************/
/*
we will need to include an enum into another menu
graphic which contains the text to overlay onto
the menugraphics
*/
typedef struct database
{
AVP_BEHAVIOUR_TYPE bhvr_type;
int num;
}DATABASE_BLOCK;
typedef struct database_template
{
int num;
VECTORCH position;
EULER orientation;
int shape_num;
} DATABASE_TOOLS_TEMPLATE;
extern void DatabaseMenus(DATABASE_BLOCK* db);
/***********************************************************/
/****************** externs for bh_types.c ******************/
/* functions*/
extern void AssignAllSBNames();
extern void AssignRunTimeBehaviours(STRATEGYBLOCK* sbptr);
extern void EnableBehaviourType(STRATEGYBLOCK* sbptr, AVP_BEHAVIOUR_TYPE sb_type, void *bhdata);
extern void ExecuteBehaviour(STRATEGYBLOCK* sbptr);
extern void ObjectBehaviours(void);
extern void RequestState(STRATEGYBLOCK* sb, int message, STRATEGYBLOCK * SBRequester);
extern BOOL GetState(STRATEGYBLOCK* sb);
extern void RemoveBehaviourStrategy(STRATEGYBLOCK* sbptr);
extern void UnlockThisProxdoor(STRATEGYBLOCK* sbptr);
extern void FindMaxZXandYAverages(VECTORCH* vect, SHAPEHEADER* shapeptr);
extern DISPLAYBLOCK *MakeObject(AVP_BEHAVIOUR_TYPE bhvr, VECTORCH *positionPtr);
extern void SetupPlayerAutoGun();
#ifdef __cplusplus
};
#endif
#endif

288
src/avp/bh_videoscreen.c Normal file
View file

@ -0,0 +1,288 @@
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "bh_videoscreen.h"
#include "dynblock.h"
#include "dynamics.h"
#include "bh_debri.h"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "pvisible.h"
void* InitVideoScreen(void* bhdata,STRATEGYBLOCK *sbPtr)
{
TOOLS_DATA_VIDEO_SCREEN *toolsData = (TOOLS_DATA_VIDEO_SCREEN *)bhdata;
VIDEO_SCREEN_BEHAV_BLOCK* videoScreen;
int i;
LOCALASSERT(sbPtr->I_SBtype == I_BehaviourVideoScreen);
LOCALASSERT(toolsData);
/* create, initialise and attach a data block */
videoScreen = (void *)AllocateMem(sizeof(VIDEO_SCREEN_BEHAV_BLOCK));
if(!videoScreen)
{
memoryInitialisationFailure = 1;
return ((void *)NULL);
}
videoScreen->bhvr_type=I_BehaviourVideoScreen;
sbPtr->SBdataptr = videoScreen;
/* set default indestructibility */
videoScreen->Indestructable = No;
/* Initialise object's stats */
//set health and armour
{
NPC_DATA *NpcData;
NpcData=GetThisNpcData(I_NPC_DefaultInanimate);
LOCALASSERT(NpcData);
sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
}
sbPtr->SBDamageBlock.Health*=toolsData->integrity;
//get a dynamics block
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
if(!sbPtr->DynPtr)
{
RemoveBehaviourStrategy(sbPtr);
return 0;
}
//is this screen indestructable
if (toolsData->integrity > 20)
{
videoScreen->Indestructable = Yes;
sbPtr->integrity = DEFAULT_OBJECT_INTEGRITY;
}
else if (toolsData->integrity < 1)
{
sbPtr->integrity = 1; // die immediately
}
else
{
sbPtr->integrity = (DEFAULT_OBJECT_INTEGRITY)*(toolsData->integrity);
}
/* Initialise the dynamics block */
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
GLOBALASSERT(dynPtr);
dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
dynPtr->OrientEuler = toolsData->orientation;
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
}
/* strategy block initialisation */
sbPtr->shapeIndex = toolsData->shapeIndex;
for(i=0;i<SB_NAME_LENGTH;i++) sbPtr->SBname[i] = toolsData->nameID[i];
/*check to see if object is animated.*/
{
TXACTRLBLK **pptxactrlblk;
int item_num;
int shape_num = toolsData->shapeIndex;
SHAPEHEADER *shptr = GetShapeData(shape_num);
pptxactrlblk = &videoScreen->inan_tac;
for(item_num = 0; item_num < shptr->numitems; item_num ++)
{
POLYHEADER *poly = (POLYHEADER*)(shptr->items[item_num]);
LOCALASSERT(poly);
SetupPolygonFlagAccessForShape(shptr);
if((Request_PolyFlags((void *)poly)) & iflag_txanim)
{
TXACTRLBLK *pnew_txactrlblk;
pnew_txactrlblk = AllocateMem(sizeof(TXACTRLBLK));
if(pnew_txactrlblk)
{
pnew_txactrlblk->tac_flags = 0;
pnew_txactrlblk->tac_item = item_num;
pnew_txactrlblk->tac_sequence = 0;
pnew_txactrlblk->tac_node = 0;
pnew_txactrlblk->tac_txarray = GetTxAnimArrayZ(shape_num, item_num);
pnew_txactrlblk->tac_txah_s = GetTxAnimHeaderFromShape(pnew_txactrlblk, shape_num);
*pptxactrlblk = pnew_txactrlblk;
pptxactrlblk = &pnew_txactrlblk->tac_next;
}
else *pptxactrlblk = NULL;
}
}
*pptxactrlblk=0;
}
//copy destruction target stuff
videoScreen->destruct_target_request=toolsData->destruct_target_request;
for(i=0;i<SB_NAME_LENGTH;i++)
{
videoScreen->destruct_target_ID[i]=toolsData->destruct_target_ID[i];
}
videoScreen->destruct_target_sbptr=0;
return((void*)videoScreen);
}
void VideoScreenBehaviour(STRATEGYBLOCK *sbPtr)
{
DISPLAYBLOCK* dptr;
VIDEO_SCREEN_BEHAV_BLOCK* videoScreen;
GLOBALASSERT(sbPtr);
videoScreen = sbPtr->SBdataptr;
GLOBALASSERT(videoScreen);
dptr = sbPtr->SBdptr;
if(dptr)
{
LIGHTBLOCK *lightPtr = dptr->ObLights[0];
//update light if near
if (lightPtr)
{
if(sbPtr->SBdptr->ObNumLights==1)
{
extern int FmvColourRed;
extern int FmvColourGreen;
extern int FmvColourBlue;
lightPtr->LightBright = ONE_FIXED;
lightPtr->LightFlags = LFlag_Omni;
lightPtr->LightType = LightType_PerVertex;
lightPtr->LightRange = 5000;
lightPtr->RedScale= FmvColourRed;
lightPtr->GreenScale= FmvColourGreen;
lightPtr->BlueScale= FmvColourBlue;
}
}
//deal with texture animation if near
if(videoScreen->inan_tac)
{
if(!dptr->ObTxAnimCtrlBlks)
{
dptr->ObTxAnimCtrlBlks = videoScreen->inan_tac;
}
}
}
}
void VideoScreenIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple)
{
VIDEO_SCREEN_BEHAV_BLOCK* videoScreen;
GLOBALASSERT(sbPtr);
videoScreen = sbPtr->SBdataptr;
GLOBALASSERT(videoScreen);
//no netweok code for this yet (if ever)
if (!videoScreen->Indestructable)
{
if(sbPtr->SBDamageBlock.Health <= 0)
{
//notify target of destruction
if(videoScreen->destruct_target_sbptr)
{
RequestState(videoScreen->destruct_target_sbptr,videoScreen->destruct_target_request,0);
}
//the object has been destroyed
MakeFragments(sbPtr);
DestroyAnyStrategyBlock(sbPtr);
}
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct video_screen_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
BOOL Indestructable;
//strategyblock stuff
int integrity;
DAMAGEBLOCK SBDamageBlock;
}VIDEO_SCREEN_SAVE_BLOCK;
void LoadStrategy_VideoScreen(SAVE_BLOCK_STRATEGY_HEADER* header)
{
STRATEGYBLOCK* sbPtr;
VIDEO_SCREEN_BEHAV_BLOCK* videoScreen;
VIDEO_SCREEN_SAVE_BLOCK* block = (VIDEO_SCREEN_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//find the existing strategy block
sbPtr = FindSBWithName(header->SBname);
if(!sbPtr) return;
//make sure the strategy found is of the right type
if(sbPtr->I_SBtype != I_BehaviourVideoScreen) return;
videoScreen = (VIDEO_SCREEN_BEHAV_BLOCK*)sbPtr->SBdataptr;
//start copying stuff
videoScreen->Indestructable = block->Indestructable;
sbPtr->integrity = block->integrity;
sbPtr->SBDamageBlock = block->SBDamageBlock;
}
void SaveStrategy_VideoScreen(STRATEGYBLOCK* sbPtr)
{
VIDEO_SCREEN_SAVE_BLOCK *block;
VIDEO_SCREEN_BEHAV_BLOCK* videoScreen;
videoScreen = (VIDEO_SCREEN_BEHAV_BLOCK*)sbPtr->SBdataptr;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//start copying stuff
block->Indestructable = videoScreen->Indestructable;
block->integrity = sbPtr->integrity;
block->SBDamageBlock = sbPtr->SBDamageBlock;
}

36
src/avp/bh_videoscreen.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef _bh_videoscreen_h
#define _bh_videoscreen_h
typedef struct video_screen_behav_block
{
AVP_BEHAVIOUR_TYPE bhvr_type;
BOOL Indestructable;
TXACTRLBLK *inan_tac;//for video screens with anims on them
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* destruct_target_sbptr;
}VIDEO_SCREEN_BEHAV_BLOCK;
typedef struct toolsdata_video_screen
{
struct vectorch position;
struct euler orientation;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
int integrity; // 0-20 (>20 = indestructable)
int destruct_target_request;
char destruct_target_ID[SB_NAME_LENGTH];
}TOOLS_DATA_VIDEO_SCREEN;
void* InitVideoScreen(void* bhdata,STRATEGYBLOCK *sbPtr);
void VideoScreenBehaviour(STRATEGYBLOCK *sbPtr);
void VideoScreenIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple);
#endif

998
src/avp/bh_waypt.c Normal file
View file

@ -0,0 +1,998 @@
/***** bh_waypt.c *****/
#include "3dc.h"
#include "inline.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "comp_shp.h"
#include "dynblock.h"
#include "dynamics.h"
#include "pfarlocs.h"
#include "pheromon.h"
#include "bh_types.h"
#include "pvisible.h"
#include "bh_far.h"
#include "bh_debri.h"
#include "bh_pred.h"
#include "bh_paq.h"
#include "bh_queen.h"
#include "bh_marin.h"
#include "bh_alien.h"
#include "lighting.h"
#include "bh_weap.h"
#include "weapons.h"
#include "psnd.h"
#define UseLocalAssert Yes
#include "ourasert.h"
/*This allows ai not to go for the shortest all the time*/
#define ALLOW_USE_OF_LONGER_PATHS Yes
int NPC_Waypoints;
int Num_Target_Waypoints;
int Global_Num_Waypoints;
int Global_NPC_Type;
WAYPOINT_ROUTE Global_Route;
static int GlobalLinkShift; //Allows different aliens to take different routes
WAYPOINT_VOLUME *Global_Target_Waypoint,*Global_NPC_Waypoint;
VECTORCH Global_Module_Offset;
/* forward declarations for this file */
int NewFindThisRoute(WAYPOINT_HEADER *waypoints, WAYPOINT_ROUTE *thisroute,WAYPOINT_VOLUME *startwaypoint, WAYPOINT_VOLUME *endwaypoint);
void SweepWaypoints(WAYPOINT_HEADER *waypoints, STRATEGYBLOCK *sbPtr, VECTORCH *targetPosition);
int FindBestRoute(WAYPOINT_ROUTE *bestroute,WAYPOINT_HEADER *waypoints);
int NPCContainsPoint(STRATEGYBLOCK *sbPtr,VECTORCH *point);
void GetTargetPositionInWaypoint(WAYPOINT_VOLUME *waypoint,VECTORCH *output);
void InitWaypointSystem(int npctype) {
Global_Route.num_waypoints=ONE_FIXED;
Global_Route.start=NULL;
Global_Route.second=NULL;
Global_Route.last=NULL;
Global_NPC_Type=npctype;
}
void InitWaypointManager(WAYPOINT_MANAGER *manager) {
manager->current_container=NULL;
manager->current_target=NULL;
manager->current_link=NULL;
manager->current_target_point.vx=0;
manager->current_target_point.vy=0;
manager->current_target_point.vz=0;
}
int NPCGetWaypointDirection(WAYPOINT_HEADER *waypoints, STRATEGYBLOCK *sbPtr, VECTORCH *velocityDirection, VECTORCH *targetPosition,WAYPOINT_MANAGER *manager) {
/* Revision of NPCGetMovementDirection, to accomodate the waypoint system. */
VECTORCH targetDirection;
WAYPOINT_ROUTE current_route;
WAYPOINT_VOLUME *dest_waypoint;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->DynPtr);
LOCALASSERT(velocityDirection);
LOCALASSERT(targetPosition);
/* I don't know if we'll need this... */
targetDirection = *targetPosition;
targetDirection.vx -= sbPtr->DynPtr->Position.vx;
targetDirection.vz -= sbPtr->DynPtr->Position.vz;
targetDirection.vy = 0;
Normalise(&targetDirection);
/*in the unlikely case that the player or npc doesnt have a current containingg module,
just return the target direction */
if((playerPherModule==NULL)||(sbPtr->containingModule==NULL))
{
*velocityDirection = targetDirection;
textprint("Waypoint dropout: no modules\n");
InitWaypointManager(manager);
return(0);
}
Global_Module_Offset=sbPtr->containingModule->m_aimodule->m_world;
Global_Route.num_waypoints=ONE_FIXED;
Global_Route.start=NULL;
Global_Route.second=NULL;
Global_Route.last=NULL;
Global_Route.first_link=NULL;
NPC_Waypoints=0;
Num_Target_Waypoints=0;
/* This will establish the locations of the NPC and the target. */
SweepWaypoints(waypoints, sbPtr, targetPosition);
/* Return the target direction if the NPC or the target have no containing waypoint. */
if ( (NPC_Waypoints==0) || (Num_Target_Waypoints==0) ) {
*velocityDirection = targetDirection;
textprint("Waypoint dropout: no containing waypoints (%d, %d)\n",NPC_Waypoints,Num_Target_Waypoints);
InitWaypointManager(manager);
return(0);
}
/* Now what? Compute the best route to the target. */
textprint("NPC is in %d waypoints.\n",NPC_Waypoints);
//Base shift value on strategy block so that the aliens don't keep changing their minds
//about which route to take
GlobalLinkShift=(((int)sbPtr)&0xffff)>>4;
if (FindBestRoute(&current_route,waypoints)==0) {
/* Yuck! */
textprint("Waypoint dropout: no continuous route!\n");
InitWaypointManager(manager);
return(0);
}
/* If the best route has start and end the same, go for it. */
Global_Route=current_route;
if ((Global_Route.start!=Global_Route.second)
&&(Global_Route.second!=Global_Route.last)) {
GLOBALASSERT(Global_Route.first_link);
}
if (current_route.start==current_route.last) {
textprint("Waypoint dropout Success: start==end\n");
*velocityDirection = targetDirection;
return(1);
}
dest_waypoint=NULL;
/* If the NPC is entirely inside the first waypoint, then head for the centre of
the second one. Else, head for the centre of the first one. */
if (NPC_Waypoints==1) {
/* Global_NPC_Waypoint must be correct. */
if (Global_NPC_Waypoint==current_route.start) {
dest_waypoint=current_route.second;
} else {
/* wtf? */
}
} else {
if (NPCContainsPoint(sbPtr,&manager->current_target_point)) {
/* Must have reached the 'centre'. */
if (Global_NPC_Waypoint==current_route.start) {
dest_waypoint=current_route.second;
} else {
/* wtf? */
}
}
}
if (dest_waypoint==NULL) {
dest_waypoint=current_route.start;
}
LOCALASSERT(dest_waypoint);
/* Right, at this point we have a route, a containing waypoint, a destination, etc. */
if (manager->current_target==dest_waypoint) {
/* Continue to head for the old target position, if it's valid. */
if (!WaypointContainsPoint(manager->current_target,&manager->current_target_point)) {
manager->current_target_point=dest_waypoint->centre;
}
} else {
/* Set destination... */
manager->current_target=dest_waypoint;
manager->current_link=Global_Route.first_link;
/* Get a new target position, based on the link we're now using. */
if (manager->current_link==NULL) {
manager->current_target_point=dest_waypoint->centre;
} else if (manager->current_link->link_flags&linkflag_largetarget) {
GetTargetPositionInWaypoint(dest_waypoint,&manager->current_target_point);
} else {
manager->current_target_point=dest_waypoint->centre;
}
}
if (manager->current_container!=Global_Route.start) {
manager->current_container=Global_Route.start;
manager->current_link=Global_Route.first_link;
/* Actually, no need to change the target... is there? */
#if ALLOW_USE_OF_LONGER_PATHS
//make it cost to enter this waypoint volume
//(encouraging ai to use other routes)
Global_Route.start->weighting++;
//if the weighting for a volume has got too high , reduce the weighting for all volumes
if(Global_Route.start->weighting>25)
{
int i;
for(i=0;i<waypoints->num_waypoints;i++)
{
//don't want to reduce weighting below the original weighting
if(waypoints->first_waypoint[i].weighting>5)
{
waypoints->first_waypoint[i].weighting--;
}
}
}
#endif
} else {
/* Er, well done. */
}
//targetDirection=dest_waypoint->centre;
targetDirection=manager->current_target_point;
targetDirection.vx+=Global_Module_Offset.vx;
targetDirection.vy+=Global_Module_Offset.vy;
targetDirection.vz+=Global_Module_Offset.vz;
targetDirection.vx -= sbPtr->DynPtr->Position.vx;
targetDirection.vz -= sbPtr->DynPtr->Position.vz;
targetDirection.vy -= sbPtr->DynPtr->Position.vy;
Normalise(&targetDirection);
{
int a,b;
b=-1;
for (a=0; a<waypoints->num_waypoints; a++) {
WAYPOINT_VOLUME *this_waypoint;
this_waypoint=waypoints->first_waypoint;
this_waypoint+=a;
if (this_waypoint==dest_waypoint) {
b=a;
}
}
textprint("Destination waypoint: %d\n",b);
}
textprint("Waypoint Generated Velocity = %d %d %d\n",targetDirection.vx,targetDirection.vy,targetDirection.vz);
*velocityDirection = targetDirection;
/* That's all folks. */
return(1);
}
int WaypointContainsPoint(WAYPOINT_VOLUME *waypoint, VECTORCH *point) {
/* 'point' should be in module space. */
int minx,maxx,miny,maxy,minz,maxz;
minx=waypoint->centre.vx+waypoint->min_extents.vx;
miny=waypoint->centre.vy+waypoint->min_extents.vy;
minz=waypoint->centre.vz+waypoint->min_extents.vz;
maxx=waypoint->centre.vx+waypoint->max_extents.vx;
maxy=waypoint->centre.vy+waypoint->max_extents.vy;
maxz=waypoint->centre.vz+waypoint->max_extents.vz;
if (point->vx>=minx) {
if (point->vx<=maxx) {
if (point->vy>=miny) {
if (point->vy<=maxy) {
if (point->vz>=minz) {
if (point->vz<=maxz) {
return(1);
}
}
}
}
}
}
return(0);
}
int WaypointContainsPoint_2d(WAYPOINT_VOLUME *waypoint, VECTORCH *point) {
/* 'point' should be in module space. */
int minx,maxx,minz,maxz;
minx=waypoint->centre.vx+waypoint->min_extents.vx;
minz=waypoint->centre.vz+waypoint->min_extents.vz;
maxx=waypoint->centre.vx+waypoint->max_extents.vx;
maxz=waypoint->centre.vz+waypoint->max_extents.vz;
if (point->vx>=minx) {
if (point->vx<=maxx) {
if (point->vz>=minz) {
if (point->vz<=maxz) {
return(1);
}
}
}
}
return(0);
}
int WaypointContainsNPC(WAYPOINT_VOLUME *volume,STRATEGYBLOCK *sbPtr) {
VECTORCH testpoint;
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->DynPtr);
LOCALASSERT(sbPtr->SBdptr);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMaxX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMaxY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMaxZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMinX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMaxY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMaxZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMaxX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMinY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMaxZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMinX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMinY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMaxZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMaxX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMaxY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMinZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMinX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMaxY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMinZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMaxX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMinY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMinZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
testpoint.vx=sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMinX-Global_Module_Offset.vx;
testpoint.vy=sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMinY-Global_Module_Offset.vy;
testpoint.vz=sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMinZ-Global_Module_Offset.vz;
if (WaypointContainsPoint(volume,&testpoint)) return(1);
/* Failed! */
return(0);
}
int NPCContainsPoint(STRATEGYBLOCK *sbPtr,VECTORCH *point) {
/* Point is in MODULESPACE! */
LOCALASSERT(point);
LOCALASSERT(sbPtr);
LOCALASSERT(sbPtr->DynPtr);
LOCALASSERT(sbPtr->SBdptr);
if (point->vx<(sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMaxX-Global_Module_Offset.vx)) {
if (point->vx>(sbPtr->DynPtr->Position.vx+sbPtr->SBdptr->ObMinX-Global_Module_Offset.vx)) {
if (point->vy<(sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMaxY-Global_Module_Offset.vy)) {
if (point->vy>(sbPtr->DynPtr->Position.vy+sbPtr->SBdptr->ObMinY-Global_Module_Offset.vy)) {
if (point->vz<(sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMaxZ-Global_Module_Offset.vz)) {
if (point->vz>(sbPtr->DynPtr->Position.vz+sbPtr->SBdptr->ObMinZ-Global_Module_Offset.vz)) {
return(1);
}
}
}
}
}
}
return(0);
}
void SweepWaypoints(WAYPOINT_HEADER *waypoints, STRATEGYBLOCK *sbPtr, VECTORCH *targetPosition) {
WAYPOINT_VOLUME *this_waypoint;
int a;
Global_Num_Waypoints=waypoints->num_waypoints;
for (a=0; a<waypoints->num_waypoints; a++) {
VECTORCH modtargetpos;
this_waypoint=waypoints->first_waypoint;
this_waypoint+=a;
this_waypoint->contains_npc=0;
this_waypoint->contains_target=0;
modtargetpos.vx=targetPosition->vx-Global_Module_Offset.vx;
modtargetpos.vy=targetPosition->vy-Global_Module_Offset.vy;
modtargetpos.vz=targetPosition->vz-Global_Module_Offset.vz;
if (WaypointContainsPoint(this_waypoint,&modtargetpos)) {
Num_Target_Waypoints++;
Global_Target_Waypoint=this_waypoint;
this_waypoint->contains_target=1;
}
if (WaypointContainsNPC(this_waypoint,sbPtr)) {
NPC_Waypoints++;
Global_NPC_Waypoint=this_waypoint;
this_waypoint->contains_npc=1;
}
}
}
void Trickle_Down(WAYPOINT_HEADER *waypoints, WAYPOINT_VOLUME *this_waypoint, int trickle_value) {
int a;
LOCALASSERT(this_waypoint->workspace<=trickle_value);
this_waypoint->workspace=trickle_value;
for (a=0; a<this_waypoint->num_links; a++) {
WAYPOINT_LINK *link_to_next;
WAYPOINT_VOLUME *next_waypoint;
link_to_next=this_waypoint->first_link;
link_to_next+=a;
if ((link_to_next->link_flags&linkflag_oneway)==0) {
next_waypoint=waypoints->first_waypoint;
next_waypoint+=link_to_next->link_target_index;
if (next_waypoint->workspace<trickle_value) {
LOCALASSERT(trickle_value>0);
Trickle_Down(waypoints,next_waypoint,trickle_value-1);
}
}
}
}
void FindThisRoute(WAYPOINT_HEADER *waypoints, WAYPOINT_ROUTE *thisroute,WAYPOINT_VOLUME *startwaypoint, WAYPOINT_VOLUME *endwaypoint) {
int a,b;
int current_trickle_value;
WAYPOINT_VOLUME *thiswaypoint;
/* Trivial case... */
if ( (startwaypoint->contains_npc) && (startwaypoint->contains_target) ) {
thisroute->num_waypoints=0;
thisroute->start=startwaypoint;
thisroute->second=startwaypoint;
thisroute->last=startwaypoint;
return;
}
/* Setup... */
thisroute->num_waypoints=0;
thisroute->start=startwaypoint;
thisroute->second=NULL;
thisroute->last=endwaypoint;
for (a=0; a<waypoints->num_waypoints; a++) {
/* Preparation... */
WAYPOINT_VOLUME *temp_waypoint;
temp_waypoint=waypoints->first_waypoint;
temp_waypoint+=a;
temp_waypoint->workspace=0;
}
current_trickle_value=waypoints->num_waypoints;
/* Not so trivial cases: cheap 'pheromone' system. */
Trickle_Down(waypoints, endwaypoint, current_trickle_value);
/* Now extract best route. */
b=0; /* Number of waypoints stepped. */
thiswaypoint=startwaypoint;
while (thiswaypoint!=endwaypoint) {
/* Look through links for highest increment. */
int nextstep=0;
WAYPOINT_VOLUME *bestnextwaypoint=NULL;
for (a=0; a<thiswaypoint->num_links; a++) {
WAYPOINT_LINK *link_to_next;
WAYPOINT_VOLUME *next_waypoint;
link_to_next=thiswaypoint->first_link;
link_to_next+=a;
if ((link_to_next->link_flags&linkflag_reversed_oneway)==0) {
next_waypoint=waypoints->first_waypoint;
next_waypoint+=link_to_next->link_target_index;
if (next_waypoint->workspace>thiswaypoint->workspace) {
if (next_waypoint->workspace>nextstep) {
/* Found a better step. */
nextstep=next_waypoint->workspace;
bestnextwaypoint=next_waypoint;
}
}
}
}
LOCALASSERT(nextstep);
LOCALASSERT(bestnextwaypoint);
if (b==0) {
thisroute->second=bestnextwaypoint;
}
b++;
thiswaypoint=bestnextwaypoint;
/* Go round again... */
}
thisroute->num_waypoints=b;
/* That may be it... */
}
int FindBestRoute(WAYPOINT_ROUTE *bestroute,WAYPOINT_HEADER *waypoints) {
int a;
WAYPOINT_ROUTE thisroute;
/* Wipe the best route... */
bestroute->num_waypoints=ONE_FIXED;
bestroute->start=NULL;
bestroute->second=NULL;
bestroute->last=NULL;
bestroute->first_link=NULL;
for (a=0; a<waypoints->num_waypoints; a++) {
WAYPOINT_VOLUME *start;
start=waypoints->first_waypoint;
start+=a;
if (start->contains_npc) {
if (NewFindThisRoute(waypoints,&thisroute,start,Global_Target_Waypoint)==0) {
/* Yuck. */
return(0);
}
/* We now have a route from this waypoint to the target. */
if (thisroute.num_waypoints<bestroute->num_waypoints) {
/* New best route. */
bestroute->num_waypoints=thisroute.num_waypoints;
bestroute->start=thisroute.start;
bestroute->second=thisroute.second;
bestroute->last=thisroute.last;
bestroute->first_link=thisroute.first_link;
}
}
}
/* We now have a best route. */
{
int start, second, last;
for (a=0; a<waypoints->num_waypoints; a++) {
WAYPOINT_VOLUME *this_waypoint;
this_waypoint=waypoints->first_waypoint;
this_waypoint+=a;
if (this_waypoint==bestroute->start) {
start=a;
}
if (this_waypoint==bestroute->second) {
second=a;
}
if (this_waypoint==bestroute->last) {
last=a;
}
}
textprint("Waypoint route: %d %d %d\n",start,second,last);
}
return(1);
}
int AlienIsAllowedToAttack(STRATEGYBLOCK *sbPtr) {
ALIEN_STATUS_BLOCK *alienStatusPtr;
/* Define rules: alien may not attack if the containing module has
waypoints, AND the target is more than one waypoint away.
Note that the waypoint system MUST have been called just a bit earlier... */
LOCALASSERT(sbPtr);
alienStatusPtr=(ALIEN_STATUS_BLOCK *)(sbPtr->SBdataptr);
LOCALASSERT(alienStatusPtr);
if (alienStatusPtr->EnableWaypoints==0) {
/* I see no waypoints. */
return(1);
}
if (sbPtr->containingModule->m_aimodule->m_waypoints!=NULL) {
if ((Global_Route.num_waypoints<2)
||(Global_Route.num_waypoints==ONE_FIXED)) {
/* ONE_FIXED = no containing waypoints dropout. */
return(1);
} else {
return(0);
}
} else {
return(1);
}
}
#define WAYVOLUME_QUEUE_LENGTH 100
typedef struct route_queue {
int depth;
WAYPOINT_VOLUME *wayvolume;
} ROUTE_QUEUE;
ROUTE_QUEUE Waypoint_Route_Queue[WAYVOLUME_QUEUE_LENGTH];
int Queue_End,Queue_Exec;
int NewFindThisRoute(WAYPOINT_HEADER *waypoints, WAYPOINT_ROUTE *thisroute,WAYPOINT_VOLUME *startwaypoint, WAYPOINT_VOLUME *endwaypoint) {
int a;
int terminate;
/* Trivial case... */
if ( (startwaypoint->contains_npc) && (startwaypoint->contains_target) ) {
thisroute->num_waypoints=0;
thisroute->start=startwaypoint;
thisroute->second=startwaypoint;
thisroute->last=startwaypoint;
thisroute->first_link=NULL;
return(1);
}
/* Setup... */
thisroute->num_waypoints=0;
thisroute->start=startwaypoint;
thisroute->second=NULL;
thisroute->last=endwaypoint;
thisroute->first_link=NULL;
for (a=0; a<waypoints->num_waypoints; a++) {
/* Preparation... */
WAYPOINT_VOLUME *temp_waypoint;
temp_waypoint=waypoints->first_waypoint;
temp_waypoint+=a;
temp_waypoint->workspace=0;
}
/* Start with the end point. Look down all the links,
add all the waypoints there to the queue. */
#if ALLOW_USE_OF_LONGER_PATHS
#define STARTING_DEPTH 5000
#else
#define STARTING_DEPTH waypoints->num_waypoints
#endif
Waypoint_Route_Queue[0].depth=STARTING_DEPTH;
Waypoint_Route_Queue[0].wayvolume=endwaypoint;
endwaypoint->workspace=Waypoint_Route_Queue[0].depth;
Waypoint_Route_Queue[1].wayvolume=NULL; /* To set a standard. */
Queue_End=1;
Queue_Exec=0;
terminate=0;
while ( (Waypoint_Route_Queue[Queue_Exec].wayvolume!=NULL)&&(terminate==0) ) {
WAYPOINT_VOLUME *this_waypoint;
int current_link=0;
this_waypoint=Waypoint_Route_Queue[Queue_Exec].wayvolume;
//don't always start with the first link so that the ai can arbitrarily
//choose between routes of equal length
if(this_waypoint->num_links)
{
current_link=GlobalLinkShift % this_waypoint->num_links;
}
for (a=0; a<this_waypoint->num_links; a++) {
WAYPOINT_LINK *link_to_next;
WAYPOINT_VOLUME *next_waypoint;
int exec_this_link;
link_to_next=this_waypoint->first_link;
link_to_next+=current_link;
current_link++;
if(current_link==this_waypoint->num_links)current_link=0;
if ( (Global_NPC_Type!=1) && (link_to_next->link_flags&linkflag_alienonly) ) {
exec_this_link=0;
} else {
exec_this_link=1;
}
if ( ((link_to_next->link_flags&linkflag_oneway)==0)&&(exec_this_link) ) {
next_waypoint=waypoints->first_waypoint;
next_waypoint+=link_to_next->link_target_index;
/* Got the next waypoint. */
if (next_waypoint==startwaypoint) {
/* Found the route. */
thisroute->start=next_waypoint;
thisroute->second=this_waypoint;
thisroute->last=endwaypoint;
thisroute->num_waypoints=1+STARTING_DEPTH-this_waypoint->workspace;
thisroute->first_link=link_to_next;
terminate=1;
textprint("Got a route.\n");
#if ALLOW_USE_OF_LONGER_PATHS
}else if (next_waypoint->workspace+next_waypoint->weighting<this_waypoint->workspace) {
/* Add to queue. */
Waypoint_Route_Queue[Queue_End].wayvolume=next_waypoint;
Waypoint_Route_Queue[Queue_End].depth=Waypoint_Route_Queue[Queue_Exec].depth-next_waypoint->weighting;
next_waypoint->workspace=Waypoint_Route_Queue[Queue_End].depth;
{
/*Need to move this new entry down the queue until the entries are sorted
by depth*/
int this_index=Queue_End;
int prev_index;
while(1)
{
prev_index=this_index-1;
if(prev_index==-1)prev_index=WAYVOLUME_QUEUE_LENGTH-1;
if(Waypoint_Route_Queue[this_index].depth>Waypoint_Route_Queue[prev_index].depth)
{
/*Swap two entries in the queue*/
int temp_depth=Waypoint_Route_Queue[this_index].depth;
WAYPOINT_VOLUME * temp_wayvolume=Waypoint_Route_Queue[this_index].wayvolume;
Waypoint_Route_Queue[this_index].depth=Waypoint_Route_Queue[prev_index].depth;
Waypoint_Route_Queue[this_index].wayvolume=Waypoint_Route_Queue[prev_index].wayvolume;
Waypoint_Route_Queue[prev_index].depth=temp_depth;
Waypoint_Route_Queue[prev_index].wayvolume=temp_wayvolume;
}
else
{
break;
}
this_index=prev_index;
}
}
Queue_End++;
if (Queue_End>=WAYVOLUME_QUEUE_LENGTH) {
Queue_End=0;
textprint("Wrapping Waypoint Queue!\n");
}
Waypoint_Route_Queue[Queue_End].wayvolume=NULL;
LOCALASSERT(Queue_End!=Queue_Exec); //if this happens the queue probably needs to be longer
}
#else
}else if (next_waypoint->workspace<this_waypoint->workspace) {
/* Add to queue. */
Waypoint_Route_Queue[Queue_End].wayvolume=next_waypoint;
Waypoint_Route_Queue[Queue_End].depth=Waypoint_Route_Queue[Queue_Exec].depth-1;
next_waypoint->workspace=Waypoint_Route_Queue[Queue_End].depth;
Queue_End++;
if (Queue_End>=WAYVOLUME_QUEUE_LENGTH) {
Queue_End=0;
textprint("Wrapping Waypoint Queue!\n");
}
Waypoint_Route_Queue[Queue_End].wayvolume=NULL;
LOCALASSERT(Queue_End!=Queue_Exec); //if this happens the queue probably needs to be longer
}
#endif
}
}
/* Done all the links. */
Queue_Exec++;
if (Queue_Exec>=WAYVOLUME_QUEUE_LENGTH) Queue_Exec=0;
}
/* Still here? */
if (terminate) {
/* We found a route! */
return(1);
} else {
/* We didn't find a route... oh dear. */
thisroute->start=startwaypoint;
thisroute->second=endwaypoint;
thisroute->last=endwaypoint;
thisroute->first_link=NULL;
/* |(&(*$*&"^)(*!*&%&%!!!!! */
return(0);
}
}
extern int AlienIsEncouragedToCrawl(void) {
if (Global_Route.first_link==NULL) {
#if 0
if (Global_Route.start!=NULL) {
if (Global_Route.second!=NULL) {
if (Global_Route.start->flags&wayflag_cancrawl) {
if (Global_Route.second->flags&wayflag_cancrawl) {
return(1);
}
}
}
}
#endif
return(0);
} else {
/* Look at this link. */
if (Global_Route.first_link->link_flags&linkflag_alienonly) {
return(1);
} else {
return(0);
}
}
}
WAYPOINT_VOLUME *GetPositionValidity(MODULE *conmod, VECTORCH *position, VECTORCH *suggestion) {
WAYPOINT_HEADER *waypoints;
WAYPOINT_VOLUME *this_waypoint,*retval;
int a;
/* Added for near bimble state. */
waypoints=conmod->m_waypoints;
retval=NULL;
if (waypoints==NULL) {
return(NULL);
}
suggestion->vx=position->vx;
suggestion->vy=position->vy;
suggestion->vz=position->vz;
for (a=0; a<waypoints->num_waypoints; a++) {
VECTORCH modtargetpos;
this_waypoint=waypoints->first_waypoint;
this_waypoint+=a;
this_waypoint->contains_npc=0;
this_waypoint->contains_target=0;
modtargetpos.vx=position->vx-conmod->m_world.vx;
modtargetpos.vy=position->vy-conmod->m_world.vy;
modtargetpos.vz=position->vz-conmod->m_world.vz;
if (WaypointContainsPoint(this_waypoint,&modtargetpos)) {
retval=this_waypoint;
}
}
if (retval) {
return(retval);
}
/* Try again, sneakily. */
for (a=0; a<waypoints->num_waypoints; a++) {
VECTORCH modtargetpos;
this_waypoint=waypoints->first_waypoint;
this_waypoint+=a;
this_waypoint->contains_npc=0;
this_waypoint->contains_target=0;
modtargetpos.vx=position->vx-conmod->m_world.vx;
modtargetpos.vy=position->vy-conmod->m_world.vy;
modtargetpos.vz=position->vz-conmod->m_world.vz;
if (WaypointContainsPoint_2d(this_waypoint,&modtargetpos)) {
retval=this_waypoint;
}
}
if (retval) {
suggestion->vy=(retval->max_extents.vy+retval->min_extents.vy)>>1;
suggestion->vy+=conmod->m_world.vy;
return(retval);
}
return(NULL);
}
void GetTargetPositionInWaypoint(WAYPOINT_VOLUME *waypoint,VECTORCH *output) {
int minx,maxx,miny,maxy,minz,maxz;
int rangex,rangey,rangez;
minx=waypoint->centre.vx+((waypoint->min_extents.vx*3)>>2);
miny=waypoint->centre.vy+((waypoint->min_extents.vy*3)>>2);
minz=waypoint->centre.vz+((waypoint->min_extents.vz*3)>>2);
maxx=waypoint->centre.vx+((waypoint->max_extents.vx*3)>>2);
maxy=waypoint->centre.vy+((waypoint->max_extents.vy*3)>>2);
maxz=waypoint->centre.vz+((waypoint->max_extents.vz*3)>>2);
rangex=maxx-minx;
rangey=maxy-miny;
rangez=maxz-minz;
output->vx=minx+(FastRandom()%rangex);
output->vy=miny+(FastRandom()%rangey);
output->vz=minz+(FastRandom()%rangez);
GLOBALASSERT(WaypointContainsPoint(waypoint,output));
}

69
src/avp/bh_waypt.h Normal file
View file

@ -0,0 +1,69 @@
/***** bh_waypt.h *****/
/***** Waypoint system code... *****/
/***** CDF 27/10/97 *****/
struct strategyblock;
typedef struct waypoint_link {
int link_target_index;
int link_flags;
} WAYPOINT_LINK;
#define linkflag_oneway 0x00000001 /* link is... get this... one way! */
#define linkflag_reversed_oneway 0x00000002 /* link is one way, only NOT this way. */
#define linkflag_alienonly 0x00000004
#define linkflag_largetarget 0x00000008
typedef struct waypoint_volume {
VECTORCH centre; /* in MODULE space! */
VECTORCH max_extents;
VECTORCH min_extents;
int flags;
int workspace:14;
unsigned int contains_npc:1;
unsigned int contains_target:1;
int num_links;
WAYPOINT_LINK *first_link;
unsigned char weighting;
} WAYPOINT_VOLUME;
#define wayflag_cancrawl 0x00000001
typedef struct waypoint_header {
int num_waypoints;
WAYPOINT_VOLUME *first_waypoint;
} WAYPOINT_HEADER;
typedef struct waypoint_route {
int num_waypoints;
WAYPOINT_VOLUME *start;
WAYPOINT_VOLUME *second;
WAYPOINT_VOLUME *last;
WAYPOINT_LINK *first_link;
} WAYPOINT_ROUTE;
typedef struct waypoint_manager {
WAYPOINT_VOLUME *current_container;
WAYPOINT_VOLUME *current_target;
WAYPOINT_LINK *current_link;
VECTORCH current_target_point;
} WAYPOINT_MANAGER;
extern void InitWaypointSystem(int npctype);
extern int NPCGetWaypointDirection(WAYPOINT_HEADER *waypoints, struct strategyblock *sbPtr, VECTORCH *velocityDirection, VECTORCH *targetPosition, WAYPOINT_MANAGER *manager);
extern int AlienIsAllowedToAttack(struct strategyblock *sbPtr);
extern int AlienIsEncouragedToCrawl(void);
extern WAYPOINT_VOLUME *GetPositionValidity(struct module *conmod, VECTORCH *position, VECTORCH *suggestion);
extern void InitWaypointManager(WAYPOINT_MANAGER *manager);

5530
src/avp/bh_weap.c Normal file

File diff suppressed because it is too large Load diff

196
src/avp/bh_weap.h Normal file
View file

@ -0,0 +1,196 @@
/***** bh_weap.h *****/
#include "particle.h"
extern void FireProjectileAmmo(enum AMMO_ID AmmoID);
extern void FrisbeeBehaviour(STRATEGYBLOCK *sbPtr);
extern void RocketBehaviour(STRATEGYBLOCK *sbPtr);
extern void GrenadeBehaviour(STRATEGYBLOCK *sbPtr);
extern void MolotovBehaviour(STRATEGYBLOCK *sbPtr);
extern void PulseGrenadeBehaviour(STRATEGYBLOCK *sbPtr);
extern void ProximityGrenadeBehaviour(STRATEGYBLOCK *sbPtr);
extern void FlareGrenadeBehaviour(STRATEGYBLOCK *sbPtr);
extern void ClusterGrenadeBehaviour(STRATEGYBLOCK *sbPtr);
extern void XenoborgEnergyBoltBehaviour(STRATEGYBLOCK *sbPtr);
extern void PredatorEnergyBoltBehaviour(STRATEGYBLOCK *sbPtr);
extern void AlienSpitBehaviour(STRATEGYBLOCK *sbPtr);
extern void NPCDiscBehaviour(STRATEGYBLOCK *sbPtr);
extern void DiscBehaviour_SeekTrack(STRATEGYBLOCK *sbPtr);
extern void PPPlasmaBoltBehaviour(STRATEGYBLOCK *sbPtr);
extern void SpeargunBoltBehaviour(STRATEGYBLOCK *sbPtr);
extern void FireFlameThrower(VECTORCH *position,VECTORCH *base_offset,MATRIXCH *orientmat, int player, int *timer);
extern void FireNetGhostFlameThrower(VECTORCH *positionPtr, MATRIXCH *orientMatPtr);
extern DISPLAYBLOCK *SpawnMolotovCocktail(SECTION_DATA *root, MATRIXCH *master_orient);
void Convert_Disc_To_Pickup(STRATEGYBLOCK *sbPtr);
void FirePredPistolFlechettes(VECTORCH *base_position,VECTORCH *base_offset,MATRIXCH *orientmat,int player,int *timer,BOOL damaging);
extern void FrisbeeEnergyBoltBehaviour(STRATEGYBLOCK *sbPtr);
extern int SBIsEnvironment(STRATEGYBLOCK *sbPtr);
typedef struct OneShotBehaviourType
{
int counter;
} ONE_SHOT_BEHAV_BLOCK;
typedef struct PredPistolBehaviourType
{
int counter;
int player;
} PREDPISTOL_BEHAV_BLOCK;
typedef struct GrenadeBehaviourType
{
int counter;
int bouncelastframe;
} GRENADE_BEHAV_BLOCK;
typedef struct
{
int LifeTimeRemaining;
int ParticleGenerationTimer;
int SoundHandle;
/*
becomeStuck set when flare hits wall.
gets reset once a network message about it has been sent
*/
unsigned int becomeStuck:1;
} FLARE_BEHAV_BLOCK;
typedef struct
{
int LifeTimeRemaining;
int SoundGenerationTimer;
int SoundHandle;
} PROX_GRENADE_BEHAV_BLOCK;
typedef struct CasterBoltBehaviourType
{
int counter;
DAMAGE_PROFILE damage;
int blast_radius;
int player;
int soundHandle;
} CASTER_BOLT_BEHAV_BLOCK;
typedef struct MolotovBehaviourType {
int counter;
HMODELCONTROLLER HModelController;
} MOLOTOV_BEHAV_BLOCK;
typedef struct FrisbeeBehaviourType
{
int counter;
HMODELCONTROLLER HModelController;
int soundHandle;
int Bounced :1;
int bounces;
LASER_BEAM_DESC Laser;
} FRISBEE_BEHAV_BLOCK;
typedef struct PCPredDiscBehaviourType
{
int counter;
STRATEGYBLOCK *Target;
char Target_SBname[SB_NAME_LENGTH];
char Prev_Target_SBname[SB_NAME_LENGTH];
char Prev_Damaged_SBname[SB_NAME_LENGTH];
HMODELCONTROLLER HModelController;
int soundHandle;
int Destruct:1;
int Stuck :1;
int Bounced :1;
int bounces;
} PC_PRED_DISC_BEHAV_BLOCK;
typedef struct SpearBehaviourType
{
int counter;
MATRIXCH Orient;
VECTORCH Position;
HMODELCONTROLLER HierarchicalFragment;
int Android;
/* behaviour type of parent object, e.g. I_BehaviourAlien */
AVP_BEHAVIOUR_TYPE Type;
int SubType;
unsigned int SpearThroughFragment;
unsigned int Stuck :1;
} SPEAR_BEHAV_BLOCK;
#define FLARE_LIFETIME 16
#define FLARE_PARTICLE_GENERATION_TIME (ONE_FIXED/120)
#define FRAG_LIFETIME 65536
#if SupportWindows95
#define NO_OF_FRAGS_IN_CLUSTER_BOMB 6
#else
#define NO_OF_FRAGS_IN_CLUSTER_BOMB 4
#endif
#define PROX_GRENADE_TRIGGER_TIME (ONE_FIXED/4)
#define PROX_GRENADE_RANGE (4000)
#define PROX_GRENADE_SOUND_GENERATION_TIME 65536
#define PROX_GRENADE_LIFETIME (20)
/* KJL 17:46:30 02/24/97 - below is some old stuff I'll leave for reference */
#if 0
extern void FlameProjectileFunction(STRATEGYBLOCK *sptr);
extern void GrenadeBehaviour(STRATEGYBLOCK *sptr);
extern void TOWMissileBehaviour(STRATEGYBLOCK *sptr);
extern void PredatorDiscBehaviour(STRATEGYBLOCK *sptr);
typedef struct OneShotBehaviourType {
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH ObWorld;
int counter;
} ONE_SHOT_BEHAV_BLOCK;
typedef struct FlameProjectileBehaviourType {
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH ObWorld;
int counter;
#if SupportMorphing
MORPHCTRL *FPmctrl;
#endif
} FLAME_PROJ_BEHAV_BLOCK;
typedef struct TowMissileBehaviourType {
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH ObWorld;
VECTORCH Target;
int counter;
} TOW_MISSILE_BEHAV_BLOCK;
typedef struct PredatorDiscBehaviourType {
AVP_BEHAVIOUR_TYPE bhvr_type;
VECTORCH ObWorld;
VECTORCH Target;
STRATEGYBLOCK *MovingTarget;
int counter;
int retargetcounter;
int phase;
} PRED_DISC_BEHAV_BLOCK;
#endif

5308
src/avp/bh_xeno.c Normal file

File diff suppressed because it is too large Load diff

234
src/avp/bh_xeno.h Normal file
View file

@ -0,0 +1,234 @@
/* Patrick 4/7/97------------------------------
Header file for xenoborg support functions
ChrisF 6/7/98 Well, sort of.
---------------------------------------------*/
#ifndef _bhxeno_h_
#define _bhxeno_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/* KJL 16:57:28 16/07/98 - particle.h is needed for LASER_BEAM_DESC */
#include "particle.h"
#include "bh_ais.h"
/* Patrick 4/7/97------------------------------
Enumerations of sequences and states
---------------------------------------------*/
typedef enum xeno_bhstate
{
XS_ActiveWait,
XS_TurnToFace,
XS_Following,
XS_Returning,
XS_Inactive,
XS_Activating,
XS_Deactivating,
XS_Avoidance,
XS_Regenerating,
XS_Dying,
XS_ShootingTheRoof,
}XENO_BHSTATE;
/* Patrick 4/7/97------------------------------
Structures for behaviour data & tools data
---------------------------------------------*/
typedef struct xenoStatusBlock
{
signed int health;
XENO_BHSTATE behaviourState;
XENO_BHSTATE lastState;
int stateTimer;
NPC_MOVEMENTDATA moveData;
NPC_WANDERDATA wanderData;
NPC_OBSTRUCTIONREPORT obstruction;
AIMODULE *my_module;
VECTORCH my_spot_therin;
VECTORCH my_orientdir_therin;
int module_range;
int UpTime;
int GibbFactor;
int Wounds;
HMODELCONTROLLER HModelController;
DELTA_CONTROLLER *head_pan;
DELTA_CONTROLLER *head_tilt;
DELTA_CONTROLLER *left_arm_pan;
DELTA_CONTROLLER *left_arm_tilt;
DELTA_CONTROLLER *right_arm_pan;
DELTA_CONTROLLER *right_arm_tilt;
DELTA_CONTROLLER *torso_twist;
STRATEGYBLOCK *Target;
char Target_SBname[SB_NAME_LENGTH];
VECTORCH targetTrackPos;
int Head_Pan;
int Head_Tilt;
int Left_Arm_Pan;
int Left_Arm_Tilt;
int Right_Arm_Pan;
int Right_Arm_Tilt;
int Torso_Twist;
int Old_Head_Pan;
int Old_Head_Tilt;
int Old_Left_Arm_Pan;
int Old_Left_Arm_Tilt;
int Old_Right_Arm_Pan;
int Old_Right_Arm_Tilt;
int Old_Torso_Twist;
/* KJL 12:23:24 09/12/98 - muzzleflashes replaced by
beam weapon thingies */
LASER_BEAM_DESC LeftMainBeam;
LASER_BEAM_DESC RightMainBeam;
/* KJL 16:56:38 16/07/98 */
LASER_BEAM_DESC TargetingLaser[3];
unsigned int headpandir :1;
unsigned int headtiltdir :1;
unsigned int leftarmpandir :1;
unsigned int leftarmtiltdir :1;
unsigned int rightarmpandir :1;
unsigned int rightarmtiltdir :1;
unsigned int torsotwistdir :1;
unsigned int headLock :1;
unsigned int leftArmLock :1;
unsigned int rightArmLock :1;
unsigned int targetSightTest :1;
unsigned int IAmFar :1;
unsigned int ShotThisFrame :1;
unsigned int FiringLeft :1;
unsigned int FiringRight :1;
unsigned int UseHeadLaser :1;
unsigned int UseLALaser :1;
unsigned int UseRALaser :1;
unsigned int HeadLaserOnTarget :1;
unsigned int LALaserOnTarget :1;
unsigned int RALaserOnTarget :1;
unsigned int head_moving :1;
unsigned int la_moving :1;
unsigned int ra_moving :1;
unsigned int torso_moving :1;
int soundHandle1;
int soundHandle2;
int incidentFlag;
int incidentTimer;
int head_whirr;
int left_arm_whirr;
int right_arm_whirr;
int torso_whirr;
char death_target_ID[SB_NAME_LENGTH];
STRATEGYBLOCK* death_target_sbptr;
int death_target_request;
WAYPOINT_MANAGER waypointManager;
}XENO_STATUS_BLOCK;
typedef struct tools_data_xeno
{
struct vectorch position;
int shapeIndex;
char nameID[SB_NAME_LENGTH];
char death_target_ID[SB_NAME_LENGTH];
int death_target_request;
struct euler starteuler;
int UpTime; /* Default to '20' */
int ModuleRange; /* Default to '7' */
}TOOLS_DATA_XENO;
/* Patrick 4/7/97------------------------------
Some defines
---------------------------------------------*/
#define XENO_STARTING_HEALTH 600
#define XENO_NEAR_SPEED 1000 /* mm/s */
#define XENO_NEAR_ACCURACY 5 /* mm per m max deviation */
#define XENO_NEAR_VIEW_WIDTH 500 /* mm */
#define XENO_CLOSE_APPROACH_DISTANCE 3000 /* mm */
#define XENO_FIRINGPOINT_INFRONT 1000 /* mm */
#define XENO_FIRINGPOINT_ACROSS 300 /* mm */
#define XENO_FIRINGPOINT_UP 100 /* mm */
#define XENO_PROJECTILESPEED 20000 /* mm/s */
#define XENO_PROJECTILEDAMAGE 10
#define XENO_SENTRY_SENSITIVITY 1500
#define XENO_FAR_MOVE_TIME ((24+(FastRandom()&0x07))*(ONE_FIXED>>4))
/* 1-2 seconds in 1/8ths of a second */
#define XENO_NEAR_TIMEBETWEENFIRING ((8+(FastRandom()&0x07))*(ONE_FIXED>>3))
#define XENO_RECOILTIME (ONE_FIXED>>1) /* 1/2 seconds */
#define XENO_ACTIVATION_TIME (ONE_FIXED) /* 1 second */
#define XENO_DEACTIVATION_TIME (ONE_FIXED) /* 1 second */
#define XENO_REGEN_TIME (ONE_FIXED*5)
#define XENO_POWERDOWN_TIME (ONE_FIXED*5)
/* 2,3 or 4*/
#define XENO_VOLLEYSIZE (2+(FastRandom()%3))
#define XENO_HEADPAN_GIMBALL (1024)
#define XENO_HEADTILT_GIMBALL (512)
#define XENO_TORSO_GIMBALL (1195)
#define XENO_LEFTARM_CW_GIMBALL (626)
#define XENO_LEFTARM_ACW_GIMBALL (910)
#define XENO_RIGHTARM_CW_GIMBALL (910)
#define XENO_RIGHTARM_ACW_GIMBALL (626)
#define XENO_ARM_PITCH_GIMBALL (1024)
#if 0
/* Original values. */
#define XENO_HEAD_LOCK_RATE (2) /* Was 0 */
#define XENO_HEAD_SCAN_RATE (3)
#define XENO_TORSO_TWIST_RATE (3)
#define XENO_ARM_LOCK_RATE (4)
#define XENO_FOOT_TURN_RATE (3)
#else
/* Let's slow everything down a wee bit. */
#define XENO_HEAD_LOCK_RATE (2) /* Was 0 */
#define XENO_HEAD_SCAN_RATE (4)
#define XENO_TORSO_TWIST_RATE (5)
#define XENO_ARM_LOCK_RATE (5)
#define XENO_FOOT_TURN_RATE (5)
#endif
/* Patrick 4/7/97------------------------------
Some prototypes
---------------------------------------------*/
void InitXenoborgBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr);
void XenoborgBehaviour(STRATEGYBLOCK *sbPtr);
void MakeXenoborgNear(STRATEGYBLOCK *sbPtr);
void MakeXenoborgFar(STRATEGYBLOCK *sbPtr);
void XenoborgIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,VECTORCH *incoming);
int XenoSight_FrustrumReject(STRATEGYBLOCK *sbtr,VECTORCH *localOffset);
#ifdef __cplusplus
}
#endif
#endif

448
src/avp/bonusabilities.c Normal file
View file

@ -0,0 +1,448 @@
/* KJL 16:14:35 09/09/98 - BonusAbilities.c */
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "stratdef.h"
#include "gamedef.h"
#include "bh_types.h"
#include "weapons.h"
#include "dynblock.h"
#include "avpview.h"
#include "load_shp.h"
#include "kzsort.h"
#include "kshape.h"
#include "pfarlocs.h"
#include "pvisible.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern int NormalFrameTime;
/* KJL 16:18:20 09/09/98 - Predator Grappling Hook */
struct GrapplingHookData
{
int IsEmbedded;
int IsEngaged;
int Tightness;
VECTORCH Position;
MATRIXCH Orientation;
int ShapeIndex;
DISPLAYBLOCK *DispPtr;
};
static struct GrapplingHookData GrapplingHook;
static DISPLAYBLOCK* CreateGrapplingHook(void);
extern void InitialiseGrapplingHook(void)
{
GrapplingHook.IsEngaged = 0;
GrapplingHook.IsEmbedded = 0;
GrapplingHook.ShapeIndex = GetLoadedShapeMSL("spear");
GrapplingHook.DispPtr = 0;
}
static void FireGrapplingHook(void);
void DisengageGrapplingHook(void);
extern void ActivateGrapplingHook(void)
{
if (GrapplingHook.IsEngaged)
{
DisengageGrapplingHook();
}
else
{
FireGrapplingHook();
}
}
static void FireGrapplingHook(void)
{
GrapplingHook.DispPtr = CreateGrapplingHook();
if (GrapplingHook.DispPtr)
{
GrapplingHook.IsEngaged = 1;
GrapplingHook.IsEmbedded = 0;
GrapplingHook.Tightness = ONE_FIXED;
/* CDF 14/4/99 Make a sound... */
Sound_Play(SID_GRAPPLE_THROW,"h");
#if 0
/* los */
GrapplingHook.Position = PlayersTarget.Position;
GrapplingHook.Orientation = Global_VDB_Ptr->VDB_Mat;
TransposeMatrixCH(&GrapplingHook.Orientation);
#endif
}
}
static DISPLAYBLOCK* CreateGrapplingHook(void)
{
STRATEGYBLOCK* sbPtr;
/* create and initialise a strategy block */
sbPtr = CreateActiveStrategyBlock();
if(!sbPtr) return NULL; /* failure */
InitialiseSBValues(sbPtr);
sbPtr->I_SBtype = I_BehaviourGrapplingHook;
AssignNewSBName(sbPtr);
/* create, initialise and attach a dynamics block */
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ROCKET);
if(sbPtr->DynPtr)
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
dynPtr->PrevPosition = dynPtr->Position = Global_VDB_Ptr->VDB_World;
GrapplingHook.Orientation = Global_VDB_Ptr->VDB_Mat;
TransposeMatrixCH(&GrapplingHook.Orientation);
dynPtr->OrientMat = GrapplingHook.Orientation;
dynPtr->LinVelocity.vx = dynPtr->OrientMat.mat31;
dynPtr->LinVelocity.vy = dynPtr->OrientMat.mat32;
dynPtr->LinVelocity.vz = dynPtr->OrientMat.mat33;
}
else
{
/* dynamics block allocation failed... */
RemoveBehaviourStrategy(sbPtr);
return NULL;
}
sbPtr->shapeIndex = GetLoadedShapeMSL("spear");
sbPtr->maintainVisibility = 0;
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
LOCALASSERT(sbPtr->containingModule);
if(!(sbPtr->containingModule))
{
/* no containing module can be found... abort*/
RemoveBehaviourStrategy(sbPtr);
return NULL;
}
{
MODULE tempModule;
DISPLAYBLOCK *dPtr;
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
VisibilityDefaultObjectMap.MapShape = sbPtr->shapeIndex;
tempModule.m_mapptr = &VisibilityDefaultObjectMap;
tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
tempModule.m_numlights = 0;
tempModule.m_lightarray = (struct lightblock *)0;
tempModule.m_extraitemdata = (struct extraitemdata *)0;
tempModule.m_dptr = NULL; /* this is important */
#if SupportWIndows95
tempModule.name = NULL; /* this is important */
#endif
AllocateModuleObject(&tempModule);
dPtr = tempModule.m_dptr;
if(dPtr==NULL)
{
RemoveBehaviourStrategy(sbPtr);
return NULL;
}
sbPtr->SBdptr = dPtr;
dPtr->ObStrategyBlock = sbPtr;
dPtr->ObMyModule = NULL;
dPtr->ObWorld = dynPtr->Position;
dPtr->ObEuler = dynPtr->OrientEuler;
dPtr->ObMat = dynPtr->OrientMat;
dPtr->ObRadius=10;
dPtr->ObMaxX=10;
dPtr->ObMinX=-10;
dPtr->ObMaxY=10;
dPtr->ObMinY=-10;
dPtr->ObMaxZ=10;
dPtr->ObMinZ=-10;
/* make displayblock a dynamic module object */
dPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
// sbPtr->SBDamageBlock.IsOnFire=1;
return dPtr;
}
}
extern void GrapplingHookBehaviour(STRATEGYBLOCK *sbPtr)
{
DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
if (!GrapplingHook.IsEmbedded)
{
COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
if(reportPtr)
{
char stickWhereYouAre = 0;
if (reportPtr->ObstacleSBPtr)
{
DISPLAYBLOCK *dispPtr = reportPtr->ObstacleSBPtr->SBdptr;
if (dispPtr)
if (dispPtr->ObMyModule && (!dispPtr->ObMorphCtrl))
{
stickWhereYouAre=1;
}
}
else
{
stickWhereYouAre = 1;
}
if(stickWhereYouAre)
{
dynPtr->IsStatic=1;
dynPtr->PrevPosition=dynPtr->Position;
GrapplingHook.Position=dynPtr->Position;
GrapplingHook.IsEmbedded=1;
/* CDF 14/4/99 Make a sound. */
Sound_Play(SID_GRAPPLE_HIT_WALL,"d",&dynPtr->Position);
return;
}
else
{
DisengageGrapplingHook();
return;
}
}
}
else
{
GrapplingHook.Tightness -= NormalFrameTime*4;
if (GrapplingHook.Tightness<0) GrapplingHook.Tightness=0;
}
}
extern void DisengageGrapplingHook(void)
{
GrapplingHook.IsEngaged = 0;
GrapplingHook.IsEmbedded = 0;
if (GrapplingHook.DispPtr)
{
RemoveBehaviourStrategy(GrapplingHook.DispPtr->ObStrategyBlock);
GrapplingHook.DispPtr=NULL;
}
}
extern void HandleGrapplingHookForces(void)
{
if (GrapplingHook.IsEmbedded)
{
DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
VECTORCH direction = GrapplingHook.Position;
int distance;
direction.vx -= dynPtr->Position.vx;
direction.vy -= dynPtr->Position.vy-1000;
direction.vz -= dynPtr->Position.vz;
distance = Approximate3dMagnitude(&direction);
if (distance>4096+1024)
{
Normalise(&direction);
dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,NormalFrameTime);
dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,NormalFrameTime);
dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,NormalFrameTime);
}
else if (distance>1024)
{
int s = MUL_FIXED((distance-1024)*16,NormalFrameTime);
Normalise(&direction);
dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,s);
dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,s);
dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,s);
dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->LinImpulse.vx,NormalFrameTime/2);
dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->LinImpulse.vy,NormalFrameTime/2);
dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->LinImpulse.vz,NormalFrameTime/2);
}
if (Approximate3dMagnitude(&dynPtr->LinImpulse)>ONE_FIXED)
{
Normalise(&dynPtr->LinImpulse);
}
}
}
extern void RenderGrapplingHook(void)
{
if (GrapplingHook.IsEngaged && GrapplingHook.DispPtr)
{
extern void D3D_DrawCable(VECTORCH *centrePtr, MATRIXCH *orientationPtr);
extern int CloakingPhase;
VECTORCH cable[46];
int i;
{
MATRIXCH mat = Global_VDB_Ptr->VDB_Mat;
TransposeMatrixCH(&mat);
cable[0].vx = Global_VDB_Ptr->VDB_World.vx-mat.mat31/128;
cable[0].vy = Global_VDB_Ptr->VDB_World.vy-mat.mat32/128+500;
cable[0].vz = Global_VDB_Ptr->VDB_World.vz-mat.mat33/128;
}
// cable[0].vx = Global_VDB_Ptr->VDB_World.vx;
// cable[0].vy = Global_VDB_Ptr->VDB_World.vy+500;
// cable[0].vz = Global_VDB_Ptr->VDB_World.vz;
for (i=1; i<46; i++)
{
cable[i].vx = ((45-i)*cable[0].vx + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vx)/45;
cable[i].vy = ((45-i)*cable[0].vy + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vy)/45;
cable[i].vz = ((45-i)*cable[0].vz + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vz)/45;
if (GrapplingHook.Tightness!=0)
{
int x = GetSin((302*i+CloakingPhase)&4095)/256;
int y = GetSin((502*i+200+CloakingPhase)&4095)/256;
int z = GetCos((302*i+100+CloakingPhase)&4095)/256;
int u = GetSin( ((4096*i)/45)&4095 );
u = MUL_FIXED(MUL_FIXED(u,u),GrapplingHook.Tightness);
cable[i].vx += MUL_FIXED(u,x);
cable[i].vy += MUL_FIXED(u,y);
cable[i].vz += MUL_FIXED(u,z);
}
}
{
MATRIXCH mat;
VECTORCH dir = cable[45];
dir.vx -= cable[0].vx;
dir.vy -= cable[0].vy;
dir.vz -= cable[0].vz;
Normalise(&dir);
MakeMatrixFromDirection(&dir,&mat);
D3D_DrawCable(cable, &mat);
}
#if 0
DISPLAYBLOCK displayblock;
displayblock.ObWorld=GrapplingHook.Position;
displayblock.ObMat=GrapplingHook.Orientation;
displayblock.ObShape=GrapplingHook.ShapeIndex;
displayblock.ObShapeData=GetShapeData(GrapplingHook.ShapeIndex);
displayblock.name=NULL;
displayblock.ObEuler.EulerX=0;
displayblock.ObEuler.EulerY=0;
displayblock.ObEuler.EulerZ=0;
displayblock.ObFlags=0;
displayblock.ObFlags2=0;
displayblock.ObFlags3=0;
displayblock.ObNumLights=0;
displayblock.ObRadius=0;
displayblock.ObMaxX=0;
displayblock.ObMinX=0;
displayblock.ObMaxY=0;
displayblock.ObMinY=0;
displayblock.ObMaxZ=0;
displayblock.ObMinZ=0;
displayblock.ObTxAnimCtrlBlks=NULL;
displayblock.ObEIDPtr=NULL;
displayblock.ObMorphCtrl=NULL;
displayblock.ObStrategyBlock=NULL;
displayblock.ShapeAnimControlBlock=NULL;
displayblock.HModelControlBlock=NULL;
displayblock.ObMyModule=NULL;
displayblock.SpecialFXFlags = 0;
displayblock.SfxPtr=0;
MakeVector(&displayblock.ObWorld, &Global_VDB_Ptr->VDB_World, &displayblock.ObView);
RotateVector(&displayblock.ObView, &Global_VDB_Ptr->VDB_Mat);
RenderThisDisplayblock(&displayblock);
{
PARTICLE particle;
particle.Colour = 0xffffffff;
particle.ParticleID = PARTICLE_LASERBEAM;
particle.Position = Player->ObStrategyBlock->DynPtr->Position;
particle.Position.vy-=1000;
particle.Offset = GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position;
particle.Size = 20;
RenderParticle(&particle);
}
#endif
}
}
/*--------------------**
** Loading and Saving **
**--------------------*/
#include "savegame.h"
typedef struct grapple_save_block
{
SAVE_BLOCK_STRATEGY_HEADER header;
int IsEmbedded;
int IsEngaged;
int Tightness;
VECTORCH Position;
MATRIXCH Orientation;
//strategy block stuff
DYNAMICSBLOCK dynamics;
}GRAPPLE_SAVE_BLOCK;
//defines for load/save macros
#define SAVELOAD_BLOCK block
#define SAVELOAD_BEHAV (&GrapplingHook)
void LoadStrategy_Grapple(SAVE_BLOCK_STRATEGY_HEADER* header)
{
GRAPPLE_SAVE_BLOCK* block = (GRAPPLE_SAVE_BLOCK*) header;
//check the size of the save block
if(header->size!=sizeof(*block)) return;
//create the grappling hook
GrapplingHook.DispPtr = CreateGrapplingHook();
if(!GrapplingHook.DispPtr) return;
//copy suff from the save block
COPYELEMENT_LOAD(IsEmbedded)
COPYELEMENT_LOAD(IsEngaged)
COPYELEMENT_LOAD(Tightness)
COPYELEMENT_LOAD(Position)
COPYELEMENT_LOAD(Orientation)
*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr = block->dynamics;
}
void SaveStrategy_Grapple(STRATEGYBLOCK* sbPtr)
{
GRAPPLE_SAVE_BLOCK* block;
GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
//copy stuff to the save block
COPYELEMENT_SAVE(IsEmbedded)
COPYELEMENT_SAVE(IsEngaged)
COPYELEMENT_SAVE(Tightness)
COPYELEMENT_SAVE(Position)
COPYELEMENT_SAVE(Orientation)
block->dynamics = *sbPtr->DynPtr;
block->dynamics.CollisionReportPtr=0;
}

8
src/avp/bonusabilities.h Normal file
View file

@ -0,0 +1,8 @@
/* KJL 12:09:35 10/09/98 - BonusAbilities.h */
/* KJL 12:09:43 10/09/98 - Grappling Hook */
extern void InitialiseGrapplingHook(void);
extern void ActivateGrapplingHook(void);
extern void HandleGrapplingHookForces(void);
extern void RenderGrapplingHook(void);
extern void DisengageGrapplingHook(void);

1292
src/avp/cconvars.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,225 @@
extern "C"
{
#include "3dc.h"
#include "ourasert.h"
#include "psndplat.h"
#include "dxlog.h"
#include "CD_player.h"
#include "avp_menus.h"
#include "gamedef.h"
#include "AvP_EnvInfo.h"
#include "dxlog.h"
};
#include "list_tem.hpp"
//lists of tracks for each level
List<int> LevelCDTracks[AVP_ENVIRONMENT_END_OF_LIST];
//lists of tracks for each species in multiplayer games
List<int> MultiplayerCDTracks[3];
static int LastTrackChosen=-1;
extern "C"
{
void EmptyCDTrackList()
{
for(int i=0;i<AVP_ENVIRONMENT_END_OF_LIST;i++)
{
while(LevelCDTracks[i].size()) LevelCDTracks[i].delete_first_entry();
}
for(i=0;i<3;i++)
{
while(MultiplayerCDTracks[i].size()) MultiplayerCDTracks[i].delete_first_entry();
}
}
#define CDTrackFileName "CD Tracks.txt"
static void ExtractTracksForLevel(char* & buffer,List<int> & track_list)
{
//search for a line starting with a #
while(*buffer)
{
if(*buffer=='#') break;
//search for next line
while(*buffer)
{
if(*buffer=='\n')
{
buffer++;
if(*buffer=='\r') buffer++;
break;
}
buffer++;
}
}
while(*buffer)
{
//search for a track number or comment
if(*buffer==';')
{
//comment , so no further info on this line
break;
}
else if(*buffer=='\n' || *buffer=='\r')
{
//reached end of line
break;
}
else if(*buffer>='0' && *buffer<='9')
{
int track=-1;
//find a number , add it to the list
sscanf(buffer,"%d",&track);
if(track>=0)
{
track_list.add_entry(track);
}
//skip to the next non numerical character
while(*buffer>='0' && *buffer<='9') buffer++;
}
else
{
*buffer++;
}
}
//go to the next line
while(*buffer)
{
if(*buffer=='\n')
{
buffer++;
if(*buffer=='\r') buffer++;
break;
}
buffer++;
}
}
void LoadCDTrackList()
{
//clear out the old list first
EmptyCDTrackList();
HANDLE file=CreateFile(CDTrackFileName,GENERIC_READ, 0, 0, OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS, 0);
if(file==INVALID_HANDLE_VALUE)
{
LOGDXFMT(("Failed to open %s",CDTrackFileName));
return;
}
char* buffer;
int file_size;
unsigned long bytes_read;
//copy the file contents into a buffer
file_size= GetFileSize(file,0);
buffer=new char[file_size+1];
ReadFile(file,buffer,file_size,&bytes_read,0);
CloseHandle(file);
char* bufferptr=buffer;
//first extract the multiplayer tracks
for(int i=0;i<3;i++)
{
ExtractTracksForLevel(bufferptr,MultiplayerCDTracks[i]);
}
//now the level tracks
for(i=0 ;i<AVP_ENVIRONMENT_END_OF_LIST;i++)
{
ExtractTracksForLevel(bufferptr,LevelCDTracks[i]);
}
delete [] buffer;
}
static unsigned int TrackSelectCounter=0;
static BOOL PickCDTrack(List<int>& track_list)
{
//make sure we have some tracks in the list
if(!track_list.size()) return FALSE;
//pick the next track in the list
unsigned int index=TrackSelectCounter % track_list.size();
TrackSelectCounter++;
//play it
CDDA_Stop();
CDDA_Play(track_list[index]);
LastTrackChosen = track_list[index];
return TRUE;
}
void CheckCDAndChooseTrackIfNeeded()
{
static enum playertypes lastPlayerType;
//are we bothering with cd tracks
if(!CDDA_IsOn()) return;
//is our current track still playing
if(CDDA_IsPlaying())
{
//if in a multiplayer game see if we have changed character type
if(AvP.Network == I_No_Network || AvP.PlayerType==lastPlayerType)
return;
//have changed character type , is the current track in the list for this character type
if(MultiplayerCDTracks[AvP.PlayerType].contains(LastTrackChosen))
return;
//Lets choose a new track then
}
if(AvP.Network == I_No_Network)
{
int level=NumberForCurrentLevel();
if(level>=0 && level<AVP_ENVIRONMENT_END_OF_LIST)
{
//pick track based on level
if(PickCDTrack(LevelCDTracks[level]))
{
return;
}
}
}
//multiplayer (or their weren't ant level specific tracks)
lastPlayerType=AvP.PlayerType;
PickCDTrack(MultiplayerCDTracks[AvP.PlayerType]);
}
void ResetCDPlayForLevel()
{
//check the number of tracks available while we're at it
CDDA_CheckNumberOfTracks();
TrackSelectCounter=0;
CDDA_Stop();
}
};

View file

@ -0,0 +1,3 @@
extern void LoadCDTrackList();
extern void CheckCDAndChooseTrackIfNeeded();
extern void ResetCDPlayForLevel();

1143
src/avp/cheatmodes.c Normal file

File diff suppressed because it is too large Load diff

521
src/avp/comp_map.c Normal file
View file

@ -0,0 +1,521 @@
#include "3dc.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "comp_shp.h"
#define UseLocalAssert Yes
#include "ourasert.h"
extern SHAPEHEADER ** mainshapelist;
extern MAPBLOCK8 Player_and_Camera_Type8[];
extern MAPBLOCK6 Empty_Object_Type6;
extern MAPBLOCK6 Term_Type6;
extern MODULEMAPBLOCK AvpCompiledMaps[];
MAPHEADER Map[]={
0,
0,
0,
0,
0,
0,
0,
&Player_and_Camera_Type8[0],
};
MAPSETVDB chnk_playcam_vdb = {
ViewDB_Flag_AdjustScale
// | ViewDB_Flag_Hazing
| ViewDB_Flag_AddSubject
| ViewDB_Flag_ImageBackdrop
| ViewDB_Flag_FullSize,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
5000, /* Hazing in */
30000, /*+ (ONE_FIXED << 0), hazing end */
0,
/*col24(200,200,200),*/ /* Background Colour */
/*col24(32,128,255),*/ /* Background Colour */
0, /* Background Colour */
/*col24(0,0,0),*/ /* Background Colour */
/*col24(255,0,0),*/ /* Background Colour */
65536 >> 2 , /* Ambience */
#if 0
VState_RelativeYRemote, /* View State */
2/*-1*/, /* View Distance */
0,0, /* Pan X,Y */
#endif
#if 1
VState_Inside, /* View State */
1, /* View Distance */
0,0, /* Pan X,Y */
#endif
};
/****************************************************************************/
MAPBLOCK6 Empty_Landscape_Type6 = {
MapType_Default,
-1, /* No shape */
0,0,0, /* Loc */
0,0,0, /* Orient */
ObFlag_MultLSrc
/*| ObFlag_BFCRO*/
| ObFlag_VertexHazing
/* Hack CONSTANTINE */
/* | ObFlag_SortFarZ */
/*| ObFlag_RSP*/
/*| ObFlag_NotVis*/
/*| ObFlag_NoColls*/, /* Flags */
#if StandardStrategyAndCollisions
StrategyI_Null, /* Strategy */
CollType_Landscape,/* e.g. Shape or Landscape */
GameCollStrat_Default, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
0, /* VDB Definition */
0 /* Interior Type */
};
MAPBLOCK6 Empty_Object_Type6 = {
MapType_Default,
-1, /* No shape */
0,0,0, /* Loc */
0,0,0, /* Orient */
ObFlag_MultLSrc |
/*| ObFlag_BFCRO*/
ObFlag_VertexHazing |
/* hack CONSTANTINE */
/* ObFlag_SortFarZ | */
/*| ObFlag_RSP*/
/*| ObFlag_NotVis*/
/*| ObFlag_NoColls*/
0, /* Flags1 (no others in this map type)*/
#if StandardStrategyAndCollisions
StrategyI_Null, /* Strategy */
0,/* e.g. Shape or Landscape */
GameCollStrat_Default, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
0, /* VDB Definition */
0 /* Interior Type */
};
MAPBLOCK6 Term_Type6 = {
/* map end */
MapType_Term,
0,
0,0,0,
0,0,0,
0, /* Flags */
#if StandardStrategyAndCollisions
0, /* Strategy */
0, /* e.g. Shape or Landscape */
0, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
0, /* VDB Definition */
0, /* Interior Type */
};
/****************************************************************************/
MAPBLOCK8 Player_and_Camera_Type8[] = {
#if SupportModules
/* Ship */
MapType_Player,
I_ShapeMarinePlayer, /*mainshapelist position 0*/
/* MapType_Camera, */
0, 0, 0, /* Loc */
0, 3062, 0, /* Orient */
ObFlag_MultLSrc
|0
|0,
/* Flags 2 */
0
/* | ObFlag2_DirectedMerge */
/* | ObFlag2_SurfaceAlign*/
/* | ObFlag2_Augmented_LFR*/
/* | ObFlag2_LFR_GuessReloc*/
/* | ObFlag2_LFR_UseFRM*/
/* | ObFlag2_FRM_VariableR */
/* | ObFlag2_NoMotionLerp*/
/*| ObFlag2_NoMerge*/
/*| ObFlag2_NoMergeDIfNear*/
/*| ObFlag2_NoMergeD*/
|0,
0
| 0, /* Flags 3 */
#if StandardStrategyAndCollisions
StrategyI_Player, /* Strategy */
0, /* e.g. Shape or Landscape */
GameCollStrat_Default, /* Game Collision Strategy */
ShapeCStrat_DoubleExtentEllipsoid, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
&chnk_playcam_vdb, /* VDB Definition */
IType_Body, /* Interior Type */
0, /* MapLightType */
#if StandardStrategyAndCollisions
0, /* MapMass */
0,0,0, /* MapNewtonV */
#endif
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0, /* MapMOffset */
/****************************************************************************/
#if 0
/* Player Ship Camera - MUST be next map object */
MapType_PlayerShipCamera,
I_ShapeCube, /* mainshapelist position 1 */
0,0,0, /* Loc */
0,0,0, /* Orient */
0
|0 /* Flags 1 */
| 0,
0, /* Flags 2 */
0, /* Flags 3 */
#if StandardStrategyAndCollisions
StrategyI_Camera, /* Strategy */
0, /* e.g. Shape or Landscape */
GameCollStrat_Default, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
&chnk_playcam_vdb, /* VDB Definition */
#if 0
IType_Default, /* Interior Type */
#else
IType_Body, /* Interior Type */
#endif
0, /* MapLightType */
#if StandardStrategyAndCollisions
0, /* MapMass */
0,0,0, /* MapNewtonV */
#endif
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0, /* MapMOffset */
#endif
/****************************************************************************/
/****************************************************************************/
/* Map End */
#endif /*SupportModules*/
MapType_Term, /* Map Type Function */
0, /* Shape */
0,0,0, /* Loc */
0,0,0, /* Orient */
0, /* Flags 1 */
0, /* Flags 2 */
0, /* Flags 3 */
#if StandardStrategyAndCollisions
0, /* Strategy */
0, /* e.g. Shape or Landscape */
0, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
0, /* VDB Definition */
0, /* Interior Type */
0, /* MapLightType */
#if StandardStrategyAndCollisions
0, /* MapMass */
0,0,0, /* MapNewtonV */
#endif
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0, /* MapMOffset */
};
/* ******************************************************************************** */
/*--------------**
** Module stuff **
**--------------*/
SCENEMODULE MainScene;
SCENEMODULE * MainSceneArray[] =
{
&MainScene,
0
};
/* these are effectively mapblock8*/
extern MODULEMAPBLOCK AvpCompiledMaps[];
MODULEMAPBLOCK AvpCompiledMaps[] = {
/****************************************************************************/
/****************************************************************************/
/* Map End */
{
MapType_Term, /* Map Type Function */
0, /* Shape */
0,0,0, /* Loc */
0,0,0, /* Orient */
0, /* Flags 1 */
0, /* Flags 2 */
0, /* Flags 3 */
#if StandardStrategyAndCollisions
0, /* Strategy */
0, /* e.g. Shape or Landscape */
0, /* Game Collision Strategy */
0, /* Shape Collision Strategy */
0, /* Landscape Collision Strategy */
#endif
0, /* VDB Definition */
0, /* Interior Type */
0, /* MapLightType */
#if StandardStrategyAndCollisions
0, /* MapMass */
0,0,0, /* MapNewtonV */
#endif
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0, /* MapMOffset */
}
};
MODULE Empty_Module = {
mtype_module, /* MODULETYPE m_type */
"null", /* char m_name[] */
0, /* int m_index */
0, /* int m_flags */
0,0,0, /* VECTOR m_world */
"null", /* MREF m_ext */
0, /* int m_ext_scale */
0, /* int m_maxx */
0, /* int m_minx */
0, /* int m_maxy */
0, /* int m_miny */
0, /* int m_maxz */
0, /* int m_minz */
0, /* MODULEMAPBLOCK *m_mapptr */
0, /* struct displayblock *m_dptr */
"null", /* MREF m_vptr */
0, /* VMODULE *m_v_ptrs */
0, /* struct module **m_link_ptrs */
// 0, /* VIEWPORT *m_viewports */
0, /* MODULETABLEHEADER *m_table */
mfun_null, /* MFUNCTION m_ifvisible */
mfun_null, /* MFUNCTION m_ifvinside */
"null", /* MREF m_funref */
0, /* Strategy block * */
0, /* num lights*/
NULL, /* pointer to light blocks*/
NULL, /* pointer to extraitemdata */
0,0,0,
0,0,0,
0,0,0,
#if SupportWindows95
0,
#endif
};
MODULE Term_Module = {
mtype_term /* MODULETYPE m_type */
};
// this is the one used for the loaded modules
MODULEMAPBLOCK Empty_Module_Map =
{
MapType_Default, /* MapType */
-1, /* MapShape */
0, 0, 0, /* MapWorld */
0, 0, 0, /* MapEuler */ /* Orient */
0
| ObFlag_MultLSrc /* MapFlags */
| ObFlag_NoInfLSrc
//| ObFlag_BFCRO
//| ObFlag_VertexHazing
| 0,
0
//| ObFlag2_SortD
| 0, /* Flags 2 */
0
| ObFlag3_ObjectSortedItems
| ObFlag3_NoLightDot
| ObFlag3_PreLit
| 0, /* Flags 3 */
0, /* VDB Definition */
0, /* Interior Type */
LightType_PerVertex, /* MapLightType */
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0, /* MapMOffset */
};
// !!!!!!!!!!!!
// Default ModuleMapBlock defined below; this will be used for
// run-time creation of both temporary, local, and global objects;
// for the most part, these objects will have no collisions, comprising
// sprite-based explosions, vertex-based explosion fragments, missiles,
// grenades, etc. They might also include "placeable" objects, like
// deposited inventory items, ammo, medpacks, etc.
// !!!!!!!!!!!!
MODULEMAPBLOCK TempModuleMap = \
{
MapType_Default, /* MapType */
-1, /* MapShape */
0, 0, 0, /* MapWorld */
0, 0, 0, /* MapEuler */ /* Orient */
0 /* flags 1*/
| ObFlag_NoInfLSrc
| ObFlag_MultLSrc
|0,
/* Flags 2 */
0,
0
// | ObFlag3_NoLightDot
| 0, /* Flags 3 */
0, /* VDB Definition */
0, /* Interior Type */
#if Saturn
LightType_PerObject, /* MapLightType */
#else
LightType_PerVertex, /* MapLightType */
#endif
0,0,0, /* MapOrigin */
0, /* MapSimShapes */
0, /* MapViewType */
0, /* MapMPtr */
0, /* MapDPtr */
0,0,0 /* MapMOffset */
};

181
src/avp/comp_shp.c Normal file
View file

@ -0,0 +1,181 @@
#include "3dc.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "comp_shp.h"
#include "mslhand.h"
#define UseLocalAssert Yes
#include "ourasert.h"
/*
There is a small problem in the destiction between
compiled in shapes and binary loaded ones. I am
changing chnkmaps.c maps.c and shapes.c into comp_shp.c
comp_shp.h, comp_map.c and comp_map.h.
We need to generate data for the game by
1. Setting up the initial Environment
2. Placing the player in the environment
3. Generateing Activer blocks at runtime.
To deal with these problems we can now do the following
1 Binary Load Shapes. Link these to MAPs and SBs
2 Have functions to modify a mapblock that describes
the player depending on how he entered a level
3 Have a list of shapes that is either Compiled in
or loaded at game init to represent the shapes that
can be generated at run time. Have a set of functions
to gnertae MAPBLOCKS for the above.
this is the compiled in shape list for AVP. For the
Saturn and the Playstation, these shapes may end up
being loaded during game init, (not level init) to
reduce the overall memory load
compiled in shapes are descriptons and strategies of
shapes AND functions to spawn mapblocks and attach
strategy blocks
To generate stuff we have a list of compiled in shapes
that are appended to the start of the mainshapelist.
We then have functions that cen generate the maps and
strategyblocks for each. Texture maps for the shapes
are read in at level init along with the rest of the
texture maps for each env.
procedure:
Generate map block using reference into
*/
#define NUM_MAR_SHAPES 14
int maxshapes=0;
SHAPEHEADER ** mainshapelist=0;
/* compiled in shapes that do not exist as yet*/
#if 0
SHAPEHEADER PULSE_header; /*Marine Weapons*/
SHAPEHEADER AASHOTGUN_header;
SHAPEHEADER CANNISTERGUN_header;
SHAPEHEADER FTHROWER_header;
SHAPEHEADER SMARTGUN_header;
SHAPEHEADER PIG_header;
SHAPEHEADER LATW_header;
SHAPEHEADER PARTICLE_header;
SHAPEHEADER ROCKET_header;
SHAPEHEADER* MarineCompiledShapes[] = {
&BOB_header,
&BOB_header,
&BOB_header, /*MarinePlayer*/
&BOB_header, /*PredatorPlayer*/
&BOB_header, /*AlienPlayer*/
&BOB_header, /* was &ALIEN_header, but the textures are no longer there. The old alien should be fully purged. << keywords: BUG FIXME OPTIMIZEME OPTIMISEME ERROR MISTAKE HACK >> */
&BOB_header,
&BOB_header,
&BOB_header,
&BOBCROUCH_header, /* player crouch shape */
&BOBLIE_header, /* player lying down shape */
&BOB_header, /* Flamethrower shot - frame 1 */
&BOB_header, /* Flamethrower shot - frame 2 */
&BOB_header,
&BOB_header, /*Marine Weapons*/
&AASHOTGUN_header,
&CANNISTERGUN_header,
&FTHROWER_header,
&SMARTGUN_header,
&PIG_header,
&LATW_header,
&PARTICLE_header,
&ROCKET_header,
&BOB_header, /* alien generator */
};
#else
// changed by John to get rid of all compiled in shapes
SHAPEHEADER* MarineCompiledShapes[] = {
&CUBE_header,
&CUBE_header,
&CUBE_header, /*MarinePlayer*/
&CUBE_header, /*PredatorPlayer*/
&CUBE_header, /*AlienPlayer*/
&CUBE_header, /* was &ALIEN_header, but the textures are no longer there. The old alien should be fully purged. << keywords: BUG FIXME OPTIMIZEME OPTIMISEME ERROR MISTAKE HACK >> */
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header, /* player crouch shape */
&CUBE_header, /* player lying down shape */
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header,
&CUBE_header, /* alien generator */
};
#endif
#define STARTOF_PRECOMPILEDSHAPES 0
int load_precompiled_shapes(void)
{
static int done = 0;
int i,j = 0;
if(!mainshapelist)
{
maxshapes=750;
/*I'm not using AllocateMem because I'll have to realloc this later*/
mainshapelist=(SHAPEHEADER**)malloc(sizeof(SHAPEHEADER*)*maxshapes);
LOCALASSERT(mainshapelist);
if(!mainshapelist)
{
ReleaseDirect3D();
exit(0x74363);
}
for(i=0;i<maxshapes;i++)
{
mainshapelist[i]=0;
}
}
i=STARTOF_PRECOMPILEDSHAPES;
if (done) return i+NUM_MAR_SHAPES;
/* KJL 11:43:36 09/24/96 - load some marine stuff hacked in 'cos the old way was even worse */
while(j < NUM_MAR_SHAPES)
{
mainshapelist[i] = MarineCompiledShapes[j];
i++;
j++;
}
done = 1;
return i;
}

49
src/avp/comp_shp.h Normal file
View file

@ -0,0 +1,49 @@
extern SHAPEHEADER** mainshapelist;
extern int start_of_loaded_shapes;
extern SHAPEHEADER CUBE_header;
extern SHAPEHEADER PRISM_header;
extern SHAPEHEADER BOB_header;
extern SHAPEHEADER ALIEN_header;
extern SHAPEHEADER BLOODSPLASH_header;
extern SHAPEHEADER BULLETRICOCHET_header;
extern SHAPEHEADER EXPLOSION_header;
extern SHAPEHEADER BOBCROUCH_header;
extern SHAPEHEADER BOBLIE_header;
extern SHAPEHEADER FLAME1_header;
extern SHAPEHEADER FLAME2_header;
extern SHAPEHEADER LGRENADE_header;
typedef enum marineshapesenum
{
I_ShapeCube,
I_ShapePrism,
I_ShapeMarinePlayer,
I_ShapePredatorPlayer,
I_ShapeAlienPlayer,
I_ShapeAlien,
I_ShapeBloodSplash,
I_ShapeBulletRicochet,
I_ShapeExplosion,
I_ShapeMarinePlayerCrouch,
I_ShapeMarinePlayerLieDown,
I_ShapeFlame1,
I_ShapeFlame2,
I_ShapeLGrenade,
I_ShapePulseRifle,
I_ShapeAAShotgun,
I_ShapeCanisterGun,
I_ShapeFThrower,
I_ShapeSmartGun,
I_ShapePig,
I_ShapeLATW,
I_ShapeParticle,
I_ShapeRocket,
I_ShapeGenerator,
} MARINE_SHAPES_ENUM;
extern int load_precompiled_shapes(void);

100
src/avp/consolelog.cpp Normal file
View file

@ -0,0 +1,100 @@
/* KJL 10:19:41 30/03/98 - ConsoleLog.cpp
This file handles the mirroring of the console text
to a log file.
*/
#include <stdlib.h>
#include <string.h>
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "stratdef.h"
#include "gamedef.h"
#include "gameplat.h"
#include "debuglog.hpp"
#include "ConsoleLog.hpp"
#include "bh_types.h"
#include "inventry.h"
#include "bh_alien.h"
#include "bh_pred.h"
#include "bh_xeno.h"
#include "bh_paq.h"
#include "bh_queen.h"
#include "bh_fhug.h"
#include "bh_marin.h"
#include "bh_debri.h"
#include "bh_weap.h"
#include "bh_agun.h"
#include "weapons.h"
LogFile ConsoleLogFile("ConsoleLog.txt");
extern "C"
{
int LogConsoleTextToFile;
extern void OutputBugReportToConsoleLogfile(char *messagePtr)
{
extern MODULE *playerPherModule;
extern struct Target PlayersTarget;
ConsoleLogFile.lprintf("\n*** AvP Automated Bug Report ****\n\n");
ConsoleLogFile.lprintf("Comment: %s\n\n", (char const*)messagePtr);
ConsoleLogFile.lprintf("Environment: %s\n", (char const*)Env_List[AvP.CurrentEnv]->main );
ConsoleLogFile.lprintf("Game type: ");
if (AvP.Network != I_No_Network)
{
ConsoleLogFile.lprintf("Multiplayer\n");
}
else
{
ConsoleLogFile.lprintf("Single player\n");
}
ConsoleLogFile.lprintf("Player's Species: ");
switch(AvP.PlayerType)
{
case I_Marine:
ConsoleLogFile.lprintf("Marine\n");
break;
case I_Alien:
ConsoleLogFile.lprintf("Alien\n");
break;
case I_Predator:
ConsoleLogFile.lprintf("Predator\n");
break;
}
ConsoleLogFile.lprintf("\nPlayer's Coords: %d,%d,%d\n",Player->ObWorld.vx,Player->ObWorld.vy,Player->ObWorld.vz);
ConsoleLogFile.lprintf("Player's Module: %d '%s'\n", playerPherModule->m_index,playerPherModule->name);
ConsoleLogFile.lprintf("Player's Module Coords: %d %d %d\n",playerPherModule->m_world.vx,playerPherModule->m_world.vy,playerPherModule->m_world.vz);
ConsoleLogFile.lprintf("Player's Target: %d %d %d\n",PlayersTarget.Position.vx,PlayersTarget.Position.vy,PlayersTarget.Position.vz);
ConsoleLogFile.lprintf("\n");
}
};
extern void OutputToConsoleLogfile(char *messagePtr)
{
if(LogConsoleTextToFile)
{
ConsoleLogFile.lprintf("%s\n", (char const*)messagePtr);
}
}

23
src/avp/consolelog.hpp Normal file
View file

@ -0,0 +1,23 @@
/* KJL 10:19:41 30/03/98 - ConsoleLog.hpp
This file handles the mirroring of the console text
to a log file.
*/
#ifndef ConsoleLog_h_included
#define ConsoleLog_h_included
extern void OutputToConsoleLogfile(char *messagePtr);
#ifdef __cplusplus
extern "C"
{
#endif
extern void OutputBugReportToConsoleLogfile(char *messagePtr);
#ifdef __cplusplus
};
#endif
#endif

602
src/avp/database.c Normal file
View file

@ -0,0 +1,602 @@
#include "3dc.h"
#include "module.h"
#include "stratdef.h"
#include "gamedef.h"
#include "equipmnt.h"
#include "saveload.h"
#include "font.h"
#include "database.h"
#include "svldplat.h"
#define UseLocalAssert Yes
#include "ourasert.h"
// extern old movement functions
extern int IDemandGoForward();
extern int IDemandSelect();
extern int IDemandGoBackward();
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
extern void LoadDatabaseMessage(void);
extern void UnloadDatabaseMessage(void);
extern void WriteDatabaseMessage(void);
unsigned char *GetTextForMenuOption(enum DB_MENUOPTION_ID optionID);
#if 0
struct MenuOptionDescriptor MenuOptionData[MAX_NO_OF_DB_MENUOPTIONS] =
{
{145,40,FJ_CENTRED}, /* DB_MENUOPTION_RESUME*/
{145,60,FJ_CENTRED}, /* DB_MENUOPTION_OPTIONS*/
{145,80,FJ_CENTRED}, /*DB_MENUOPTION_MISSION*/
{145,100,FJ_CENTRED},/* DB_MENUOPTION_LOAD, */
{145,120,FJ_CENTRED},/* DB_MENUOPTION_SAVE, */
{145,140,FJ_CENTRED},/* DB_MENUOPTION_QUIT, */
{145,80,FJ_CENTRED}, /*DB_MENUOPTION_YESQUIT*/
{145,100,FJ_CENTRED},/*DB_MENUOPTION_NO*/
{237,150,FJ_CENTRED},/* DB_MENUOPTION_GOBACK, */
{125,90,FJ_CENTRED},/* DB_MENUOPTION_ACCESSDENIED */
{30,30,FJ_LEFT_JUST},/*SLOT0*/
{30,45,FJ_LEFT_JUST},/*SLOT1*/
{30,60,FJ_LEFT_JUST},/*SLOT2*/
{30,75,FJ_LEFT_JUST},/*SLOT3*/
{30,90,FJ_LEFT_JUST},/*SLOT4*/
{30,105,FJ_LEFT_JUST},/*SLOT5*/
{30,120,FJ_LEFT_JUST},/*SLOT6*/
{30,135,FJ_LEFT_JUST},/*SLOT7*/
};
#else
struct MenuOptionDescriptor MenuOptionData[MAX_NO_OF_DB_MENUOPTIONS] =
{
{0,(ONE_FIXED*4)/32,FJ_CENTRED}, /* DB_MENUOPTION_RESUME*/
{0,(ONE_FIXED*7)/32,FJ_CENTRED}, /* DB_MENUOPTION_OPTIONS*/
{0,(ONE_FIXED*10)/32,FJ_CENTRED}, /* DB_MENUOPTION_MISSION*/
{0,(ONE_FIXED*13)/32,FJ_CENTRED}, /* DB_MENUOPTION_LOAD, */
{0,(ONE_FIXED*16)/32,FJ_CENTRED}, /* DB_MENUOPTION_SAVE, */
{0,(ONE_FIXED*19)/32,FJ_CENTRED}, /* DB_MENUOPTION_QUIT, */
{0,(ONE_FIXED*10)/32,FJ_CENTRED}, /* DB_MENUOPTION_YESQUIT*/
{0,(ONE_FIXED*13)/32,FJ_CENTRED}, /* DB_MENUOPTION_NO*/
{0,(ONE_FIXED*16)/32,FJ_CENTRED}, /* DB_MENUOPTION_STARTMENU*/
{0,(ONE_FIXED*29)/32,FJ_CENTRED}, /* DB_MENUOPTION_GOBACK, */
{0,(ONE_FIXED*16)/32,FJ_CENTRED}, /* DB_MENUOPTION_ACCESSDENIED */
{(ONE_FIXED*1)/32,(ONE_FIXED*4)/32,FJ_LEFT_JUST}, /*SLOT0*/
{(ONE_FIXED*1)/32,(ONE_FIXED*7)/32,FJ_LEFT_JUST}, /*SLOT1*/
{(ONE_FIXED*1)/32,(ONE_FIXED*10)/32,FJ_LEFT_JUST}, /*SLOT2*/
{(ONE_FIXED*1)/32,(ONE_FIXED*13)/32,FJ_LEFT_JUST}, /*SLOT3*/
{(ONE_FIXED*1)/32,(ONE_FIXED*16)/32,FJ_LEFT_JUST}, /*SLOT4*/
{(ONE_FIXED*1)/32,(ONE_FIXED*19)/32,FJ_LEFT_JUST}, /*SLOT5*/
{(ONE_FIXED*1)/32,(ONE_FIXED*22)/32,FJ_LEFT_JUST}, /*SLOT6*/
{(ONE_FIXED*1)/32,(ONE_FIXED*25)/32,FJ_LEFT_JUST}, /*SLOT7*/
};
#endif
/* KJL 13:09:25 03/17/97 - to be rewritten after alpha */
unsigned char *TestMenuOptionText[] =
{
"RESUME",
"OPTIONS",
"MISSION",
"LOAD",
"SAVE",
"QUIT",
"QUIT TO WINDOWS",
"RESUME",
"QUIT TO START MENU",
"BACK",
"ACCESS DENIED",
"1:",
"2:",
"3:",
"4:",
"5:",
"6:",
"7:",
"8:",
};
static int NumberOfCurrentDbOptions;
static enum DB_MENUOPTION_ID CurrentDbOptions[MAX_NO_OF_DB_MENUOPTIONS];
static struct DatabaseInput DatabaseInput={0,0,0};
static enum DB_STATE_ID CurrentState;
static int DBStateHasChanged;
void SetupDatabaseState(enum DB_STATE_ID stateID);
void ClearMenuOptions(void);
void AddMenuOption(enum DB_MENUOPTION_ID optionID);
void ActUponChosenOption(enum DB_MENUOPTION_ID optionID);
enum DB_MENUOPTION_ID DisplayCurrentDatabaseState(enum DB_STATE_ID stateID);
void LoadGraphicsForDatabaseState(enum DB_STATE_ID stateID);
void UnloadGraphicsForDatabaseState(enum DB_STATE_ID stateID);
void DrawSpecialGraphicsForState(enum DB_STATE_ID stateID);
/* fns that should be platform specific but aren't yet */
void GetDatabaseInput(void);
void DrawDatabaseMenuOption(enum DB_MENUOPTION_ID optionID, int highlighted);
void DrawDatabaseTextString(unsigned char *textPtr, int x, int y, FONT_JUST justification, int highlighted);
unsigned char *GetTextForMenuOption(enum DB_MENUOPTION_ID optionID);
void AccessDatabase(int databaseID)
{
CurrentState = DB_STATE_MAINMENU;
PlatformSpecificEnteringDatabase();
/* database main loop */
while(CurrentState != DB_STATE_RESUME)
{
enum DB_MENUOPTION_ID chosenOption;
/* load gfx and setup menu options for current state */
SetupDatabaseState(CurrentState);
/* display state and let user select option */
chosenOption = DisplayCurrentDatabaseState(CurrentState);
/* kill gfx for current state */
UnloadGraphicsForDatabaseState(CurrentState);
/* act upon chosen option, which usually changes state */
ActUponChosenOption(chosenOption);
}
PlatformSpecificExitingDatabase();
}
void SetupDatabaseState(enum DB_STATE_ID stateID)
{
LoadGraphicsForDatabaseState(stateID);
ClearMenuOptions();
switch (stateID)
{
case DB_STATE_MAINMENU:
{
AddMenuOption(DB_MENUOPTION_RESUME);
AddMenuOption(DB_MENUOPTION_OPTIONS);
AddMenuOption(DB_MENUOPTION_MISSION);
AddMenuOption(DB_MENUOPTION_LOAD);
AddMenuOption(DB_MENUOPTION_SAVE);
AddMenuOption(DB_MENUOPTION_QUIT);
break;
}
case DB_STATE_OPTIONS:
{
AddMenuOption(DB_MENUOPTION_GOBACK);
break;
}
case DB_STATE_QUIT:
{
AddMenuOption(DB_MENUOPTION_MAINMENU);
AddMenuOption(DB_MENUOPTION_YESQUIT);
AddMenuOption(DB_MENUOPTION_NO);
break;
}
case DB_STATE_MISSION:
{
AddMenuOption(DB_MENUOPTION_GOBACK);
break;
}
case DB_STATE_LOAD:
{
AddMenuOption(DB_MENUOPTION_SAVESLOT0);
AddMenuOption(DB_MENUOPTION_SAVESLOT1);
AddMenuOption(DB_MENUOPTION_SAVESLOT2);
AddMenuOption(DB_MENUOPTION_SAVESLOT3);
AddMenuOption(DB_MENUOPTION_SAVESLOT4);
AddMenuOption(DB_MENUOPTION_SAVESLOT5);
AddMenuOption(DB_MENUOPTION_SAVESLOT6);
AddMenuOption(DB_MENUOPTION_SAVESLOT7);
AddMenuOption(DB_MENUOPTION_GOBACK);
break;
}
case DB_STATE_SAVE:
{
AddMenuOption(DB_MENUOPTION_SAVESLOT0);
AddMenuOption(DB_MENUOPTION_SAVESLOT1);
AddMenuOption(DB_MENUOPTION_SAVESLOT2);
AddMenuOption(DB_MENUOPTION_SAVESLOT3);
AddMenuOption(DB_MENUOPTION_SAVESLOT4);
AddMenuOption(DB_MENUOPTION_SAVESLOT5);
AddMenuOption(DB_MENUOPTION_SAVESLOT6);
AddMenuOption(DB_MENUOPTION_SAVESLOT7);
AddMenuOption(DB_MENUOPTION_GOBACK);
break;
}
case DB_STATE_ACCESSDENIED:
{
AddMenuOption(DB_MENUOPTION_ACCESSDENIED);
break;
}
default:
{
/* not a valid state, assert */
LOCALASSERT(0);
break;
}
}
}
void ClearMenuOptions(void)
{
NumberOfCurrentDbOptions=0;
}
void AddMenuOption(enum DB_MENUOPTION_ID optionID)
{
CurrentDbOptions[NumberOfCurrentDbOptions] = optionID;
NumberOfCurrentDbOptions++;
}
void ActUponChosenOption(enum DB_MENUOPTION_ID optionID)
{
switch (optionID)
{
case DB_MENUOPTION_RESUME:
{
CurrentState = DB_STATE_RESUME;
DBStateHasChanged = 1;
break;
}
case DB_MENUOPTION_OPTIONS:
{
CurrentState = DB_STATE_ACCESSDENIED;
DBStateHasChanged = 1;
break;
}
case DB_MENUOPTION_MISSION:
{
CurrentState = DB_STATE_MISSION;
DBStateHasChanged = 1;
break;
}
case DB_MENUOPTION_LOAD:
{
CurrentState = DB_STATE_LOAD;
// LoadGameFromFile();
break;
}
case DB_MENUOPTION_SAVE:
{
CurrentState = DB_STATE_SAVE;
// SaveGameToFile();
break;
}
case DB_MENUOPTION_NO:
case DB_MENUOPTION_GOBACK:
case DB_MENUOPTION_ACCESSDENIED:
{
/* return to main menu */
CurrentState = DB_STATE_MAINMENU;
DBStateHasChanged = 1;
break;
}
case DB_MENUOPTION_SAVESLOT0:
case DB_MENUOPTION_SAVESLOT1:
case DB_MENUOPTION_SAVESLOT2:
case DB_MENUOPTION_SAVESLOT3:
case DB_MENUOPTION_SAVESLOT4:
case DB_MENUOPTION_SAVESLOT5:
case DB_MENUOPTION_SAVESLOT6:
case DB_MENUOPTION_SAVESLOT7:
{
if(DB_STATE_LOAD == CurrentState)
{
LoadSaveSlot(optionID - DB_MENUOPTION_SAVESLOT0);
}
if(DB_STATE_SAVE == CurrentState)
{
SaveSaveSlot(optionID - DB_MENUOPTION_SAVESLOT0);
}
CurrentState = DB_STATE_RESUME;
break;
}
case DB_MENUOPTION_QUIT:
{
CurrentState = DB_STATE_QUIT;
DBStateHasChanged = 1;
break;
}
case DB_MENUOPTION_YESQUIT:
{
ExitSystem();
exit(0);
}
case DB_MENUOPTION_MAINMENU:
{
AvP.MainLoopRunning = 0;
CurrentState = DB_STATE_RESUME;
break;
}
default:
{
/* invalid option */
LOCALASSERT(0);
break;
}
}
}
static int selectedOption;
enum DB_MENUOPTION_ID DisplayCurrentDatabaseState(enum DB_STATE_ID stateID)
{
int selectionNotMade = 1;
selectedOption = 0;
LOCALASSERT(NumberOfCurrentDbOptions != 0);
do
{
// JCWH 18/02/98: allow ALT+TAB
CheckForWindowsMessages();
/* draw background */
DrawDatabaseBackground();
/* draw weapons, maps etc. as required */
DrawSpecialGraphicsForState(stateID);
/* draw all menu options */
{
int o;
for (o=0; o<NumberOfCurrentDbOptions; o++)
{
if (o == selectedOption)
DrawDatabaseMenuOption(CurrentDbOptions[o],1);
else
DrawDatabaseMenuOption(CurrentDbOptions[o],0);
}
}
/* update screen */
UpdateDatabaseScreen();
/* allow user to select an option */
GetDatabaseInput();
if (DatabaseInput.RequestSelectItem)
{
selectionNotMade=0;
}
else if (DatabaseInput.RequestPreviousItem)
{
if (selectedOption == 0)
{
selectedOption = NumberOfCurrentDbOptions;
}
selectedOption--;
}
else if (DatabaseInput.RequestNextItem)
{
selectedOption++;
if (selectedOption == NumberOfCurrentDbOptions)
{
selectedOption = 0;
}
}
}
while(selectionNotMade);
return(CurrentDbOptions[selectedOption]);
}
void LoadGraphicsForDatabaseState(enum DB_STATE_ID stateID)
{
switch (stateID)
{
case DB_STATE_MISSION:
{
LoadDatabaseMessage();
break;
}
default:
break;
}
}
void UnloadGraphicsForDatabaseState(enum DB_STATE_ID stateID)
{
switch (stateID)
{
case DB_STATE_MISSION:
{
UnloadDatabaseMessage();
break;
}
default:
break;
}
}
void DrawSpecialGraphicsForState(enum DB_STATE_ID stateID)
{
if(stateID == DB_STATE_MISSION)
{
WriteDatabaseMessage();
}
if((stateID == DB_STATE_LOAD) || (stateID == DB_STATE_SAVE))
{
char game_name[GAME_NAME_LENGTH];
int i = GAME_NAME_LENGTH, j;
while(i-- > 0)
{
*(game_name + i) = 0;
}
i = NUM_SAVE_SLOTS;
while(i-- >0)
{
FONT_DESC packet;
int posx, posy;
AVP_FONTS font_num = DATABASE_FONT_DARK;
j = GAME_NAME_LENGTH;
while(j-- > 0)
{
*(game_name + j) = 0;
}
ReadSaveSlotGameName(i, game_name);
posx = ((MenuOptionData[i + DB_MENUOPTION_SAVESLOT0].X*ScreenDescriptorBlock.SDB_Width) >> 16) + 20;
posy = ((MenuOptionData[i + DB_MENUOPTION_SAVESLOT0].Y*ScreenDescriptorBlock.SDB_Height) >> 16);
if(selectedOption == i)
{
font_num = DATABASE_FONT_LITE;
}
packet.fontnum = font_num;
packet.string = game_name;
packet.destx = posx;
packet.desty = posy;
packet.just = FJ_LEFT_JUST;
packet.width = ScreenDescriptorBlock.SDB_Width;
BLTString(packet);
}
}
}
/* platform specific fns */
static int debounced = 0;
void GetDatabaseInput(void)
{
ReadUserInput();
DatabaseInput.RequestSelectItem = 0;
DatabaseInput.RequestPreviousItem = 0;
DatabaseInput.RequestNextItem = 0;
if (IDemandSelect())
{
if (debounced)
{
DatabaseInput.RequestSelectItem =1;
debounced = 0;
}
}
else if (IDemandGoBackward())
{
if (debounced)
{
DatabaseInput.RequestNextItem =1;
debounced = 0;
}
}
else if (IDemandGoForward())
{
if (debounced)
{
DatabaseInput.RequestPreviousItem =1;
debounced = 0;
}
}
else
{
debounced=1;
}
}
void DrawDatabaseMenuOption(enum DB_MENUOPTION_ID optionID, int highlighted)
{
unsigned char *textPtr = GetTextForMenuOption(optionID);
DrawDatabaseTextString
(
textPtr,
MenuOptionData[optionID].X,
MenuOptionData[optionID].Y,
MenuOptionData[optionID].justification,
highlighted
);
}
void DrawDatabaseTextString
(
unsigned char *textPtr,
int x,
int y,
FONT_JUST justification,
int highlighted)
{
FONT_DESC packet;
if (highlighted) packet.fontnum = DATABASE_FONT_LITE;
else packet.fontnum = DATABASE_FONT_DARK;
packet.string = textPtr;
packet.destx = (x*ScreenDescriptorBlock.SDB_Width) >>16;
packet.desty = (y*ScreenDescriptorBlock.SDB_Height) >>16;
packet.just = justification;
packet.width = ScreenDescriptorBlock.SDB_Width;
BLTString(packet);
}
unsigned char *GetTextForMenuOption(enum DB_MENUOPTION_ID optionID)
{
return TestMenuOptionText[optionID];
}
int DatabaseStateChange()
{
if(DBStateHasChanged)
{
DBStateHasChanged = 0;
return 1;
}
return 0;
}

72
src/avp/database.h Normal file
View file

@ -0,0 +1,72 @@
#define NUM_SAVE_SLOTS 10
enum DB_STATE_ID
{
DB_STATE_MAINMENU,
DB_STATE_QUIT,
DB_STATE_OPTIONS,
DB_STATE_MISSION,
DB_STATE_LOAD,
DB_STATE_SAVE,
DB_STATE_RESUME,
DB_STATE_ACCESSDENIED,
MAX_NO_OF_DB_STATES
};
enum DB_MENUOPTION_ID
{
DB_MENUOPTION_RESUME,
DB_MENUOPTION_OPTIONS,
DB_MENUOPTION_MISSION,
DB_MENUOPTION_LOAD,
DB_MENUOPTION_SAVE,
DB_MENUOPTION_QUIT,
DB_MENUOPTION_YESQUIT,
DB_MENUOPTION_NO,
DB_MENUOPTION_MAINMENU,
DB_MENUOPTION_GOBACK,
DB_MENUOPTION_ACCESSDENIED,
DB_MENUOPTION_SAVESLOT0,
DB_MENUOPTION_SAVESLOT1,
DB_MENUOPTION_SAVESLOT2,
DB_MENUOPTION_SAVESLOT3,
DB_MENUOPTION_SAVESLOT4,
DB_MENUOPTION_SAVESLOT5,
DB_MENUOPTION_SAVESLOT6,
DB_MENUOPTION_SAVESLOT7,
MAX_NO_OF_DB_MENUOPTIONS
};
struct DatabaseInput
{
unsigned char RequestSelectItem :1;
unsigned char RequestPreviousItem :1;
unsigned char RequestNextItem :1;
};
struct MenuOptionDescriptor
{
/* top-left coords */
int X;
int Y;
FONT_JUST justification;
};
extern void AccessDatabase(int databaseID);
/* KJL 15:43:16 04/11/97 - platform specific */
extern void PlatformSpecificEnteringDatabase(void);
extern void PlatformSpecificExitingDatabase(void);
extern void DrawDatabaseBackground(void);
extern void UpdateDatabaseScreen(void);
extern int DatabaseStateChange();

596
src/avp/davehook.cpp Normal file
View file

@ -0,0 +1,596 @@
/*******************************************************************
*
* DESCRIPTION: davehook.cpp
*
* AUTHOR: David Malcolm
*
* HISTORY: Created 18/11/97
*
*******************************************************************/
/* Includes ********************************************************/
#include "3dc.h"
#include "davehook.h"
#include "r2base.h"
// hooks to R2 code
#include "gadget.h"
// hooks to gadgets code
#include "daemon.h"
// hooks to daemon code
#include "rentrntq.h"
//#include "ammo666.hpp"
#include "iofocus.h"
//#include "statpane.h"
#include "font.h"
#include "hudgadg.hpp"
#include "consvar.hpp"
#include "conscmnd.hpp"
#include "missions.hpp"
#include "rebmenus.hpp"
#include "indexfnt.hpp"
// Includes for console variables:
#include "textexp.hpp"
// Includes for console commands:
#include "consvar.hpp"
#include "modcmds.hpp"
#include "trepgadg.hpp"
#include "consbind.hpp"
#include "consbtch.hpp"
#define UseLocalAssert Yes
#include "ourasert.h"
#include "frontend/avp_menus.h"
/* Version settings ************************************************/
/* Constants *******************************************************/
#define DEFAULT_KEY_STATUS_PANEL_WEAPONS ( KEY_TAB )
#define DEFAULT_KEY_STATUS_PANEL_INVENTORY ( KEY_V )
#define DEFAULT_KEY_STATUS_PANEL_OBJECTIVES ( KEY_O )
#define DEFAULT_KEY_STATUS_PANEL_GAMESTATS ( KEY_G )
/* Macros **********************************************************/
/* Imported function prototypes ************************************/
/* Imported data ***************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
extern unsigned char KeyboardInput[];
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
extern int VideoModeColourDepth;
extern int bEnableTextprint;
extern int bEnableTextprintXY;
extern signed int HUDTranslucencyLevel;
#if 0
extern OurBool DaveDebugOn;
extern FDIEXTENSIONTAG FDIET_Dummy;
extern IFEXTENSIONTAG IFET_Dummy;
extern FDIQUAD FDIQuad_WholeScreen;
extern FDIPOS FDIPos_Origin;
extern FDIPOS FDIPos_ScreenCentre;
extern IFOBJECTLOCATION IFObjLoc_Origin;
extern UncompressedGlobalPlotAtomID UGPAID_StandardNull;
extern IFCOLOUR IFColour_Dummy;
extern IFVECTOR IFVec_Zero;
#endif
#ifdef __cplusplus
};
#endif
/* Exported globals ************************************************/
#if 0
int FixP_Test = (ONE_FIXED/2);
#endif
/* Internal type definitions ***************************************/
/* Internal function prototypes ************************************/
namespace Testing
{
void VVTest(void);
void VITest(int);
int IVTest(void);
int IITest(int);
void DumpRefCounts(void);
void DumpVideoMode(void);
};
static void davehook_HandleStatusPanelControls(void);
static int bFirstFrame = No;
/* Internal globals ************************************************/
/* Exported function definitions ***********************************/
/*static*/ void ConsoleVariable :: CreateAll(void)
{
// hook to create all the console variables
// (to make it easy to add new ones)
MakeSimpleConsoleVariable_Int
(
TextExpansion :: bVerbose, // int& Value_ToUse,
"EXPV", // ProjChar* pProjCh_ToUse,
"(VERBOSE REPORTS OF TEXT EXPANSIONS)", // ProjChar* pProjCh_Description_ToUse
0, // int MinVal_New,
1 // int MaxVal_New
);
#if 0
MakeSimpleConsoleVariable_Int
(
bEnableTextprint, // int& Value_ToUse,
"TEXT", // ProjChar* pProjCh_ToUse,
"(ENABLE/DISABLE DIAGNOSTIC TEXT)", // ProjChar* pProjCh_Description_ToUse
0, // int MinVal_New,
1 // int MaxVal_New
);
MakeSimpleConsoleVariable_Int
(
bEnableTextprintXY, // int& Value_ToUse,
"TEXTXY", // ProjChar* pProjCh_ToUse,
"(ENABLE/DISABLE POSITIONED TEXT)", // ProjChar* pProjCh_Description_ToUse
0, // int MinVal_New,
1 // int MaxVal_New
);
MakeSimpleConsoleVariable_Int
(
HUDTranslucencyLevel, // int& Value_ToUse,
"HUDALPHA", // ProjChar* pProjCh_ToUse,
"(OPACITY OF HEAD-UP-DISPLAY)", // ProjChar* pProjCh_Description_ToUse
0, // int MinVal_New,
255 // int MaxVal_New
);
MakeSimpleConsoleVariable_FixP
(
FixP_Test, // int& Value_ToUse,
"FIXPTEST", // ProjChar* pProjCh_ToUse,
"(A TEST)", // ProjChar* pProjCh_Description_ToUse
0, // int MinVal_New,
65536 // int MaxVal_New
);
MakeSimpleConsoleVariable_FixP
(
Daemon :: DaemonTimeScale, // int& Value_ToUse,
"IO-TIME", // ProjChar* pProjCh_ToUse,
"TIMESCALE FOR USER INTERFACE", // ProjChar* pProjCh_Description_ToUse
655, // int MinVal_New,
65536 // int MaxVal_New
);
MakeSimpleConsoleVariable_Int
(
KeyBinding :: bEcho,
"ECHO-BIND",
"(ENABLES ECHOING OF STRINGS BOUND TO KEYS)",
0,
1
);
MakeSimpleConsoleVariable_Int
(
BatchFileProcessing :: bEcho,
"ECHO-BATCH",
"(ENABLES ECHOING OF BATCH FILES)",
0,
1
);
#endif
}
/*static*/ void ConsoleCommand :: CreateAll(void)
{
Make
(
"LISTCMD",
"LIST ALL CONSOLE COMMANDS",
ListAll
);
Make
(
"LISTEXP",
"LIST ALL TEXT EXPANSIONS",
TextExpansion :: ListAll
);
Make
(
"LISTVAR",
"LIST ALL CONSOLE VARIABLES",
ConsoleVariable :: ListAllVariables
);
// Need to add
#if 0
static void AttemptToBind
(
SCString* pSCString_Key, // description of key
SCString* pSCString_ToBind // string to be bound
);
static void AttemptToUnbind
(
SCString* pSCString_Key // description of key
);
#endif
Make
(
"LISTBIND",
"LIST ALL KEY BINDINGS",
KeyBinding::ListAllBindings
);
Make
(
"UNBIND-ALL",
"GET RID OF ALL KEY BINDINGS",
KeyBinding::UnbindAll
);
#if 0
Make
(
"LISTMOD",
"LIST ALL MODULES",
ModuleCommands :: ListModules
);
Make
(
"C-KILL",
"CLEAR TEXT REPORT QUEUE",
TextReportGadget :: ClearTheQueue
);
Make
(
"D-REFDUMP",
"DIAGNOSTICS ON REFERENCE COUNTS",
Testing :: DumpRefCounts
);
Make
(
"VIDMODE",
"DUMP INFO ON VIDEO MODE",
Testing :: DumpVideoMode
);
#endif
#if 0
Make
(
"VVTEST",
"TEST COMMAND",
Testing :: VVTest
);
Make
(
"VITEST",
"TEST COMMAND",
Testing :: VITest
);
Make
(
"IVTEST",
"TEST COMMAND",
Testing :: IVTest
);
Make
(
"IITEST",
"TEST COMMAND",
Testing :: IITest
);
#endif
}
void DAVEHOOK_Init(void)
{
SCString* pSCString_TestLeak = new SCString("this is a test memory leak");
MissionHacks :: TestInit();
{
DAEMON_Init();
// AmmoDaemon :: Init();
}
new IndexedFont_HUD(DATABASE_MESSAGE_FONT);
GADGET_Init();
#if UseGadgets
ConsoleVariable :: CreateAll();
ConsoleCommand :: CreateAll();
#endif
#if 0//UseRebMenus
{
RebMenus :: Init();
}
#endif
}
void DAVEHOOK_UnInit(void)
{
#if 0//UseRebMenus
{
RebMenus :: UnInit();
}
#endif
IndexedFont :: UnloadFont(DATABASE_MESSAGE_FONT);
GADGET_UnInit();
}
void DAVEHOOK_Maintain(void)
{
{
// AmmoDaemon :: Maintain();
DAEMON_Maintain();
}
#if KeyBindingUses_KEY_ID
{
KeyBinding :: Maintain();
}
#endif
// Hacked in input support:
#if SupportWindows95
{
#if EnableStatusPanels
davehook_HandleStatusPanelControls();
#endif
#if 0
if ( KeyboardInput[ KEY_J ] )
{
// Test jitter hack
HUDGadget* pHUD = HUDGadget :: GetHUD();
if ( pHUD )
{
pHUD -> Jitter(ONE_FIXED);
}
}
#endif
#if 0
if ( KeyboardInput[ KEY_CR ] )
{
IOFOCUS_Toggle();
#if 0
// toggle typing/control mode
textprint("\n\n\n\nTOGGLE TYPING MODE\n");
#endif
}
#endif
}
#endif // SupportWindows95
#if SupportWindows95
if ( bFirstFrame )
{
RE_ENTRANT_QUEUE_WinMain_FlushMessagesWithoutProcessing();
// this is a hack to ensure that none of the keypresses used
// in the menu get through to the first frame of the game and
// for example, switch to typing mode (for CR presses)
bFirstFrame = No;
}
else
{
// Flush the WinProc messages:
RE_ENTRANT_QUEUE_WinMain_FlushMessages();
}
#endif // SupportWindows95
/* KJL 20:14:23 28/03/98 - for now I've disabled the calls to the menus while in-game */
#if 0//UseRebMenus
{
RebMenus :: Maintain();
RebMenus :: Render();
}
#endif
}
void DAVEHOOK_ScreenModeChange_Setup(void)
{
}
void DAVEHOOK_ScreenModeChange_Cleanup(void)
{
R2BASE_ScreenModeChange_Cleanup();
GADGET_ScreenModeChange_Cleanup();
#if 0
LoadPFFont(MENU_FONT_1);
#endif
bFirstFrame = Yes;
// to ensure a flush without processing of messages in first frame, so as to
// avoid carriage returns/enter from menu selections triggering typing mode
// Run program-generated batch file:
#if !(PREDATOR_DEMO|MARINE_DEMO||ALIEN_DEMO||DEATHMATCH_DEMO)
BatchFileProcessing :: Run("CONFIG.CFG");
// Run user-generated batch file:
BatchFileProcessing :: Run("STARTUP.CFG");
#endif
}
/* Internal function definitions ***********************************/
void Testing :: VVTest(void)
{
textprint("Testing :: VVTest()\n");
}
void Testing :: VITest(int i)
{
textprint("Testing :: VITest(%i)\n",i);
}
int Testing :: IVTest(void)
{
textprint("Testing :: IVTest()\n");
return 180;
}
int Testing :: IITest(int i)
{
textprint("Testing :: IITest(%i)\n",i);
return (i*2);
}
// Diagnostic hook for reference counting system:
void Testing :: DumpRefCounts(void)
{
#if TrackReferenceCounted
{
SCString* pSCString_Feedback = new SCString("DUMPING REFCOUNT INFO");
pSCString_Feedback -> SendToScreen();
pSCString_Feedback -> R_Release();
LogFile tempLog("REFDUMP.TXT");
RefCountObject :: DumpAll(tempLog);
}
#else
{
SCString* pSCString_Feedback = new SCString("REFCOUNT INFO DISABLED AT COMPILE-TIME");
pSCString_Feedback -> SendToScreen();
pSCString_Feedback -> R_Release();
}
#endif
}
void Testing :: DumpVideoMode(void)
{
char msg[256];
sprintf
(
msg,
"VIDEO MODE:%iX%iX%i",
ScreenDescriptorBlock . SDB_Width,
ScreenDescriptorBlock . SDB_Height,
VideoModeColourDepth
);
SCString* pSCString_Feedback = new SCString(msg);
pSCString_Feedback -> SendToScreen();
pSCString_Feedback -> R_Release();
}
#if EnableStatusPanels
static void davehook_HandleStatusPanelControls(void)
{
/*
DHM 27/1/98:
------------
This code ought to be rewritten in terms of the PLAYER_INPUT_CONFIGURATION
code in USR_IO.C
I've done it as a bit of a hack here to avoid messing up people's saved
control config files, and because there's no more room on the control config
screen for redefining these keys.
It will depend on whether the status panels stay in the final version.
*/
if ( IOFOCUS_AcceptControls())
{
if
(
KeyboardInput[ DEFAULT_KEY_STATUS_PANEL_WEAPONS ]
)
{
STATPANE_RequestStatusPanel
(
I_StatusPanel_Weapons
);
return;
}
if
(
KeyboardInput[ DEFAULT_KEY_STATUS_PANEL_INVENTORY ]
)
{
STATPANE_RequestStatusPanel
(
I_StatusPanel_Inventory
);
return;
}
if
(
KeyboardInput[ DEFAULT_KEY_STATUS_PANEL_OBJECTIVES ]
)
{
STATPANE_RequestStatusPanel
(
I_StatusPanel_Objectives
);
return;
}
if
(
KeyboardInput[ DEFAULT_KEY_STATUS_PANEL_GAMESTATS ]
)
{
STATPANE_RequestStatusPanel
(
I_StatusPanel_GameStats
);
return;
}
}
STATPANE_NoRequestedPanel();
}
#endif // EnableStatusPanels

45
src/avp/davehook.h Normal file
View file

@ -0,0 +1,45 @@
/*
davehook.h
Created 18/11/97 by DHM:
Contains all the hooks for my code
*/
#ifndef _davehook
#define _davehook 1
#ifdef __cplusplus
extern "C" {
#endif
/* Version settings *****************************************************/
/* Constants ***********************************************************/
/* Macros ***************************************************************/
/* Type definitions *****************************************************/
/* Exported globals *****************************************************/
/* Function prototypes **************************************************/
extern void DAVEHOOK_Init(void);
extern void DAVEHOOK_UnInit(void);
extern void DAVEHOOK_Maintain(void);
extern void DAVEHOOK_ScreenModeChange_Setup(void);
extern void DAVEHOOK_ScreenModeChange_Cleanup(void);
/* End of the header ****************************************************/
#ifdef __cplusplus
};
#endif
#endif

Some files were not shown because too many files have changed in this diff Show more