Descent3/manage/generic.cpp
2024-04-15 21:43:29 -06:00

2570 lines
79 KiB
C++

/*
* $Logfile: /DescentIII/Main/manage/generic.cpp $
* $Revision: 100 $
* $Date: 9/06/01 10:32a $
* $Author: Matt $
*
*
* $Log: /DescentIII/Main/manage/generic.cpp $
*
* 100 9/06/01 10:32a Matt
* Added code to fix problem poping add-on pages when the original pages
* were in the extra.gam file.
*
* 99 4/19/00 5:27p Matt
* From Duane for 1.4
* Mac file extension change
*
* 98 10/26/99 3:30p Jeff
* handle extra.gam addon tablefile
*
* 97 10/22/99 10:41p Jeff
* correctly merged and handle this mac code merge stuff
*
* 96 10/22/99 6:04p Jeff
* fixed bugs and compiler errors resulting from mac code merge
*
* 95 10/22/99 2:56p Kevin
* Mac merge w/memory savings
*
* 94 9/18/99 8:49p Jeff
* fixed bug with addon pages that have dependencies on other pages in the
* addon tablefile
*
* 93 8/11/99 5:32p Jeff
* changes to fix addon tablefile support so it works correctly
*
* 92 4/25/99 10:19p Matt
* Fixed multiplayer and demo problems will killing an object from script,
* and cleaned up the death code a bit in the process.
*
* 91 4/22/99 7:08p Matt
* Reduced the number of object sounds from 3 to 2, since we were only
* using two.
*
* 90 4/19/99 3:57p Matt
* Took out guidebot velocity hack.
*
* 89 4/18/99 4:49p Matt
* Took out code that hacked in ammo amounts for weapon powerups, and
* added code to set the counts on the page and read and write to the
* table file.
*
* 88 4/15/99 5:21p Jason
* sped up table file loading
*
* 87 4/14/99 1:33a Jeff
* fixed case mismatched #includes
*
* 86 4/10/99 5:56p Matt
* Cleaned up object initialization code, including create object & load
* object.
*
* 85 4/06/99 6:02p Matt
* Added score system
*
* 84 3/29/99 11:20a Matt
* Added more flexibility to death delays, and added fade away deaths.
*
* 83 3/27/99 2:15p Jason
* took out bashing of hangturret
*
* 82 3/09/99 1:44p Kevin
* Bashed the aiming point value for the hangturret.
*
* 81 3/04/99 4:47p Jason
* temp fix (ie BAD HACK) for OEM table file woes
*
* 80 2/28/99 6:20p Matt
* Added the ability to set death types for generic objects.
*
* 79 2/23/99 12:39p Jason
* added more options for generic objects
*
* 78 2/23/99 11:02a Matt
* Changed generic object spew info to use -1 for none
*
* 77 2/23/99 10:19a Matt
* Temporary fix
*
* 76 2/16/99 12:38a Matt
* Took out gunboy sound hack
*
* 75 2/02/99 8:44a Chris
* I made buildings with AI work correctly (ie really big robots should be
* buildings)
* anim to and from states are now shorts instead of bytes
*
* 74 1/21/99 11:16p Jeff
* pulled out some structs and defines from header files and moved them
* into seperate header files so that multiplayer dlls don't require major
* game headers, just those new headers. Side effect is a shorter build
* time. Also cleaned up some header file #includes that weren't needed.
* This affected polymodel.h, object.h, player.h, vecmat.h, room.h,
* manage.h and multi.h
*
* 73 1/13/99 7:04a Jeff
* put #ifdef around #include <windows.h>
*
* 72 12/30/98 5:17p Jeff
* changes made to handle script name override, to override the name of
* the script to use in a module.
*
* 71 12/29/98 4:30p Jason
* added add-on data functionality
*
* 70 12/17/98 7:26p Jeff
* new script system data
*
* 69 12/01/98 4:31p Chris
*
* 68 12/01/98 4:31p Chris
* Checked in a massive amount of AI work. Improved flocking code. :)
* (Still hacked lightly). In addition, I am moving toward using the
* composite dir. :)
*
* 67 11/19/98 8:36p Chris
* Tweaked
*
* 66 11/19/98 8:26p Chris
* Starting to add generic team avoidance code
*
* 65 11/13/98 12:30p Jason
* changes for weapons
*
* 64 11/06/98 12:35p Jason
* more speedups for manage system
*
* 63 11/05/98 7:54p Jason
* changes for new manage system
*
* 62 11/02/98 6:02p Jason
* made yes network updates much faster
*
* 61 10/23/98 6:43p Matt
* Kill the gunboy's sounds (for the demo).
*
* 60 10/12/98 11:38p Jeff
* wrapped all the Object_info[].description whenever freed...trying to
* find an obscure bug. Added icon_name to manage page of Generic
*
* 59 10/09/98 2:27p Jason
* reorganized table file system
*
* 58 10/08/98 10:03p Jason
* more filtered table file stuff
*
* 57 9/22/98 2:29p Kevin
* moved ships allowed code out of dll and into main app. Also added
* powerup exclusions
*
* 56 8/26/98 8:07p Jason
* added directional lights to objects
*
* 55 8/25/98 3:42p Jason
* fixed generic object problems
*
* 54 8/24/98 2:37p Jason
* made table file more efficient with regards to invalid names
*
* 53 8/19/98 6:29p Chris
*
* 52 8/16/98 6:17p Chris
* Added generic object spewing code
*
* 51 8/15/98 6:12p Chris
* Added 13 new AI fields
*
* 50 8/14/98 4:56p Jeff
* added quad fire mask for weapon battery
*
* 49 6/12/98 1:06p Jason
* added smart loading from local table file
*
* 48 6/04/98 6:44p Jason
* implemented smart FindGenericPage function
*
* 47 6/01/98 10:37a Matt
* Added system to spew powerups when the player dies. Still needs Jason
* to deal with mng_FindSpecificGenericPage().
*
* 46 5/18/98 8:06p Chris
* Removed an unused AI value
*
* 45 5/07/98 1:41p Chris
* Added hit_death_dot
*
* 44 5/03/98 5:38p Chris
* Added sounds to anim page
*
* 43 4/30/98 12:22p Jason
* did some lo-res model optimizations
*
* 42 4/03/98 10:07a Chris
* Added support for objects getting their size computed when the
* polymodel is paged in the first time as an object
*
* 41 4/02/98 3:54p Jason
* first pass in getting polymodel paging to work
*
* 40 3/31/98 3:49p Jason
* added memory lib
*
* 39 3/23/98 10:03a Chris
* Added independant wb animations
*
* 38 3/13/98 5:55p Chris
* Added the new collision spheres
*
* 37 3/11/98 4:59p Chris
* Changed the ComputeDefualtSize function call
*
* 36 3/10/98 6:54p Chris
* All start and end frame for ComputeDefaultSize
*
* 35 3/02/98 6:56p Chris
* Changed melee_dist to melee_damage
*
* 34 3/02/98 6:43p Chris
*
* 33 3/02/98 4:16p Chris
* Added 14 new fields to the AI Settings Dialog/page.
*
* 32 2/23/98 1:22p Jason
* made FindSpecific* read from the local drive, not the net drive - when
* starting the editor
*
* 31 2/06/98 2:15a Chris
* Activated the max_velocity, max_delta_velocity, and max_turn_rate
* fields for AI objects.
*
* 30 2/04/98 11:47a Jason
* added dynamic description field to generic pages
*
* 29 1/29/98 3:29p Chris
* Major update to the AI system.
*
* 28 1/23/98 6:25p Jason
* Got spray weapons working
*
* 27 1/15/98 6:22p Jason
* added safety checks so the network won't copy over a primitive you have
* held locally
*
* 26 1/05/98 3:55p Chris
* Added explosion and ambient sounds
*
* 25 12/22/97 6:19p Chris
* Moved weapon battery firing sound off the projectile (weapon) and into
* the weapon battery.
*
* 24 12/01/97 9:54a Chris
* Added support for concussive forces, generalized robot collisions to
* generic collisions
*
* 23 11/25/97 1:16p Jason
* added lod system for certain objects
*
* 22 11/17/97 10:47p Jason
* fixed loading/saving of flicker_distance
*
* 21 11/05/97 12:22p Chris
* Fixed size of wb_info in the page file
*
* 20 11/06/97 11:09a Jason
* added extra assert to catch errors
*
* 19 10/28/97 12:23p Chris
* We now save out more AI info
*
* 18 10/01/97 11:01a Chris
* Added new support for additional physics items
*
* 17 9/24/97 6:18p Samir
* Use script names instead of script id values to identify scripts.
*
* 16 9/17/97 10:59a Chris
* Added a new way to compute radi
*
* 15 9/10/97 5:26p Jason
* fixed stupid off by one bug
*
* 14 9/10/97 5:17p Jason
* more lighting improvements
*
* 13 9/10/97 11:44a Chris
* Added support for weapon batteries
*
* 12 9/08/97 11:51a Chris
* Extended the weapon system
*
* 11 9/05/97 1:29p Jason
* revamped generic object lighting
*
* 10 9/04/97 5:49p Jason
* made generic pages read/write pulse time for lighting
*
* 9 9/04/97 3:21p Jason
* added pulse timing for lit objects
*
* 8 9/03/97 6:18p Jason
* added code to support powerups/robots/etc that cast light
*
* 7 9/03/97 2:12p Chris
* Added new weapon battery system and made the animation system usable.
*
* 6 8/13/97 4:54p Matt
* Added destroyable flag & hitpoints
*
* 5 8/11/97 6:47p Matt
* Fixed read/write size mismatches in generic page
*
* 4 8/11/97 1:53p Matt
* Ripped out robot & powerup pages, and added generic page
*
* 3 8/08/97 5:25p Matt
* Type was writing as byte but reading as int
*
* 2 8/08/97 3:44p Jason
* added code to support new generic page
*
* 1 8/08/97 1:29p Jason
* file for object_info pages
*
* $NoKeywords: $
*/
#if defined(WIN32)
#include <windows.h>
#endif
#include "CFILE.H"
#include "manage.h"
#include "genericpage.h"
#include "soundpage.h"
#include "weaponpage.h"
#include "mono.h"
#include "pserror.h"
#include "polymodel.h"
#include "ddio.h"
#include <string.h>
#include "robotfire.h"
#include "weapon.h"
#include "sounds.h"
#include "mem.h"
#include "args.h"
#define GENERICFILE_VERSION 27
// genericpage commands that are read/written
// A command is followed by a byte count describing how many bytes
// are in the data for the command
#define GENERICPAGE_COMMAND_NAME 1
#define GENERICPAGE_COMMAND_END 2
#define GENERICPAGE_COMMAND_IMAGE_NAME 3
#define GENERICPAGE_COMMAND_VERSION 4
#define GENERICPAGE_COMMAND_PHYS_MASS 5
#define GENERICPAGE_COMMAND_PHYS_DRAG 6
#define GENERICPAGE_COMMAND_SIZE 7
#define GENERICPAGE_COMMAND_ANIM_STATES 8
#define GENERICPAGE_COMMAND_FLAGS 9
#define GENERICPAGE_COMMAND_PHYS_FLAGS 10
//AI info
#define GENERICPAGE_COMMAND_AI_INFO 11
#define GENERICPAGE_COMMAND_TYPE 12
#define GENERICPAGE_COMMAND_SCORE 13
#define GENERICPAGE_COMMAND_SCRIPT 14
#define GENERICPAGE_COMMAND_SOUND_NAME 15
#define GENERICPAGE_COMMAND_HITPOINTS 16
#define GENERICPAGE_COMMAND_LIGHT_CAST 17
#define GENERICPAGE_COMMAND_WB_INFO 18
#define GENERICPAGE_COMMAND_WB_WEAPON 19
#define GENERICPAGE_COMMAND_SCRIPTNAME 20
#define GENERICPAGE_COMMAND_ROT_DRAG 21
#define GENERICPAGE_COMMAND_FULL_THRUST 22
#define GENERICPAGE_COMMAND_FULL_ROTTHRUST 23
#define GENERICPAGE_COMMAND_TURNROLL_RATE 24
#define GENERICPAGE_COMMAND_TURNROLL_RATIO 25
#define GENERICPAGE_COMMAND_WIGGLE_AMP 26
#define GENERICPAGE_COMMAND_WIGGLE_FREQ 27
#define GENERICPAGE_COMMAND_INT_VELOCITY 28
#define GENERICPAGE_COMMAND_INT_ROTVEL 29
#define GENERICPAGE_COMMAND_NUM_BOUNCES 30
#define GENERICPAGE_COMMAND_COEFF_REST 31
#define GENERICPAGE_COMMAND_FLICKER_DISTANCE 32
#define GENERICPAGE_COMMAND_LOD_MODELS 33
// Impact stuff
#define GENERICPAGE_COMMAND_IMPACT 34
#define GENERICPAGE_COMMAND_WB_FIRE_SOUND 35
#define GENERICPAGE_COMMAND_WB_FLAGS 36
#define GENERICPAGE_COMMAND_DESCRIPTION 37
#define GENERICPAGE_COMMAND_AI_SOUND_NAME 38
#define GENERICPAGE_COMMAND_LOD_DISTANCE 39
#define GENERICPAGE_COMMAND_ANIM_SOUND_NAME 40
#define GENERICPAGE_COMMAND_HIT_DIE_DOT 41
#define GENERICPAGE_COMMAND_WB_QUADMASK 42
#define GENERICPAGE_COMMAND_AI_INFO2 43
#define GENERICPAGE_COMMAND_DSPEW_INFO 44
#define GENERICPAGE_COMMAND_DIRECTION_DOT 45
#define GENERICPAGE_COMMAND_ICON_NAME 46
void mng_WriteLightingChunk ( light_info *lighting_info,CFILE *outfile);
void mng_ReadLightingChunk (light_info *lighting_info,CFILE *infile);
extern bool Running_editor;//in init.cpp
extern char *TablefileNameOverride;
// Sets a page structure to default values
void mng_InitGenericPage (mngs_generic_page *genericpage)
{
int i;
memset (genericpage,0,sizeof(mngs_generic_page));
strcpy (genericpage->image_name,"");
strcpy (genericpage->med_image_name,"");
strcpy (genericpage->lo_image_name,"");
for (i=0;i<MAX_OBJ_SOUNDS;i++)
strcpy (genericpage->sound_name[i],"");
for (i=0;i<MAX_AI_SOUNDS;i++)
strcpy (genericpage->ai_sound_name[i],"");
for (i = 0; i < MAX_DSPEW_TYPES; i++)
{
strcpy(genericpage->dspew_name[i],"\0");
}
genericpage->objinfo_struct.description = NULL;
genericpage->objinfo_struct.icon_name[0] = '\0';
for (i=0;i<NUM_MOVEMENT_CLASSES;i++)
for (int j=0;j<NUM_ANIMS_PER_CLASS;j++)
strcpy (genericpage->anim_sound_name[i][j],"");
genericpage->objinfo_struct.med_lod_distance=DEFAULT_MED_LOD_DISTANCE;
genericpage->objinfo_struct.lo_lod_distance=DEFAULT_LO_LOD_DISTANCE;
genericpage->objinfo_struct.phys_info.hit_die_dot = 1.0f;
genericpage->objinfo_struct.respawn_scalar = 1.0f;
genericpage->ai_info.curiousity = .5f;
genericpage->ai_info.night_vision = .7f;
genericpage->ai_info.fog_vision = .7f;
genericpage->ai_info.lead_accuracy = 1.0f;
genericpage->ai_info.lead_varience = 0.0f;
genericpage->ai_info.fire_spread = 0.0f;
genericpage->ai_info.fight_team = 0.15f;
genericpage->ai_info.fight_same = 0.8f;
genericpage->ai_info.agression = 0.5f;
genericpage->ai_info.hearing = 1.0f;
genericpage->ai_info.frustration = 0.5f;
genericpage->ai_info.roaming = 0.5f;
genericpage->ai_info.life_preservation = 0.0f;
genericpage->objinfo_struct.module_name[0] = '\0';
for (i=0;i<MAX_DEATH_TYPES;i++) {
genericpage->objinfo_struct.death_types[i].flags = 0;
genericpage->objinfo_struct.death_types[i].delay_min = 0.0;
genericpage->objinfo_struct.death_types[i].delay_max = 0.0;
genericpage->objinfo_struct.death_probabilities[i] = 0;
}
}
// Given an open file pointer and a generic_page struct, writes that generic page out
void mng_WriteGenericPage (CFILE *outfile,mngs_generic_page *genericpage)
{
int i,size;
ASSERT (outfile!=NULL);
ASSERT (genericpage!=NULL);
ASSERT ((strlen(genericpage->image_name))>2);
cf_WriteByte (outfile,PAGETYPE_GENERIC);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_VERSION);
cf_WriteByte (outfile,1);
cf_WriteByte (outfile,GENERICFILE_VERSION);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_TYPE);
cf_WriteByte (outfile,1);
cf_WriteByte (outfile,genericpage->objinfo_struct.type);
// Write the name
cf_WriteByte (outfile,GENERICPAGE_COMMAND_NAME);
cf_WriteByte (outfile,strlen(genericpage->objinfo_struct.name)+1);
cf_WriteString (outfile,genericpage->objinfo_struct.name);
// Write the model name
cf_WriteByte (outfile,GENERICPAGE_COMMAND_IMAGE_NAME);
cf_WriteByte (outfile,strlen(genericpage->image_name)+1);
cf_WriteString (outfile,genericpage->image_name);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_IMPACT);
cf_WriteByte (outfile, 3*sizeof(float));
cf_WriteFloat(outfile, genericpage->objinfo_struct.impact_size);
cf_WriteFloat(outfile, genericpage->objinfo_struct.impact_time);
cf_WriteFloat(outfile, genericpage->objinfo_struct.damage);
// Write the LOD model names
cf_WriteByte (outfile,GENERICPAGE_COMMAND_LOD_MODELS);
size=strlen(genericpage->med_image_name)+1;
size+=strlen(genericpage->lo_image_name)+1;
cf_WriteByte (outfile,size);
cf_WriteString (outfile,genericpage->med_image_name);
cf_WriteString (outfile,genericpage->lo_image_name);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_SCORE);
cf_WriteByte (outfile,1);
cf_WriteByte (outfile,genericpage->objinfo_struct.score);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_SCRIPTNAME);
cf_WriteByte (outfile,strlen("")+1);//genericpage->objinfo_struct.script_name
cf_WriteString (outfile,"");
if (genericpage->objinfo_struct.description!=NULL)
{
cf_WriteByte (outfile,GENERICPAGE_COMMAND_DESCRIPTION);
cf_WriteByte (outfile,strlen(genericpage->objinfo_struct.description)+1);
cf_WriteString (outfile,genericpage->objinfo_struct.description);
}
if (genericpage->objinfo_struct.icon_name[0]!='\0')
{
cf_WriteByte (outfile,GENERICPAGE_COMMAND_ICON_NAME);
cf_WriteByte (outfile,strlen(genericpage->objinfo_struct.icon_name)+1);
cf_WriteString (outfile,genericpage->objinfo_struct.icon_name);
}
cf_WriteByte (outfile,GENERICPAGE_COMMAND_LOD_DISTANCE);
cf_WriteByte (outfile,8);
cf_WriteFloat (outfile,genericpage->objinfo_struct.med_lod_distance);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lo_lod_distance);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_PHYS_MASS);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.mass);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_PHYS_DRAG);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.drag);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_SIZE);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.size);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_LIGHT_CAST);
cf_WriteByte (outfile,(10*4)+2);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.light_distance);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.red_light1);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.green_light1);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.blue_light1);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.time_interval);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.red_light2);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.green_light2);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.blue_light2);
cf_WriteInt (outfile,genericpage->objinfo_struct.lighting_info.flags);
cf_WriteInt (outfile,genericpage->objinfo_struct.lighting_info.timebits);
cf_WriteByte (outfile,genericpage->objinfo_struct.lighting_info.angle);
cf_WriteByte (outfile,genericpage->objinfo_struct.lighting_info.lighting_render_type);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_FLICKER_DISTANCE);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.flicker_distance);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_DIRECTION_DOT);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lighting_info.directional_dot);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_HITPOINTS);
cf_WriteByte (outfile,4);
cf_WriteInt (outfile,genericpage->objinfo_struct.hit_points);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_FLAGS);
cf_WriteByte (outfile,4);
cf_WriteInt (outfile,genericpage->objinfo_struct.flags);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_PHYS_FLAGS);
cf_WriteByte (outfile,4);
cf_WriteInt (outfile,genericpage->objinfo_struct.phys_info.flags);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_ROT_DRAG);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.rotdrag);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_FULL_THRUST);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.full_thrust);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_FULL_ROTTHRUST);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.full_rotthrust);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_TURNROLL_RATE);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.max_turnroll_rate);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_TURNROLL_RATIO);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.turnroll_ratio);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WIGGLE_AMP);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.wiggle_amplitude);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WIGGLE_FREQ);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.wiggles_per_sec);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_INT_VELOCITY);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.velocity.z);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_INT_ROTVEL);
cf_WriteByte (outfile,12);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.rotvel.x);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.rotvel.y);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.rotvel.z);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_NUM_BOUNCES);
cf_WriteByte (outfile,4);
cf_WriteInt (outfile,genericpage->objinfo_struct.phys_info.num_bounces);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_COEFF_REST);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.coeff_restitution);
cf_WriteByte (outfile, GENERICPAGE_COMMAND_HIT_DIE_DOT);
cf_WriteByte (outfile,4);
cf_WriteFloat (outfile,genericpage->objinfo_struct.phys_info.hit_die_dot);
cf_WriteByte (outfile,GENERICPAGE_COMMAND_AI_INFO);
cf_WriteByte (outfile, 76);
cf_WriteInt (outfile, genericpage->ai_info.flags);
cf_WriteByte (outfile, genericpage->ai_info.ai_class);
cf_WriteByte (outfile, genericpage->ai_info.ai_type);
cf_WriteByte (outfile, genericpage->ai_info.movement_type);
cf_WriteByte (outfile, genericpage->ai_info.movement_subtype);
cf_WriteFloat(outfile, genericpage->ai_info.fov);
cf_WriteFloat(outfile, genericpage->ai_info.max_velocity);
cf_WriteFloat(outfile, genericpage->ai_info.max_delta_velocity);
cf_WriteFloat(outfile, genericpage->ai_info.max_turn_rate);
cf_WriteFloat(outfile, genericpage->ai_info.avoid_friends_distance);
// Makes sure there are no bugs as things are added and removed -- ask chris
genericpage->ai_info.notify_flags &= ~AI_NOTIFIES_ALWAYS_ON;
cf_WriteInt (outfile, genericpage->ai_info.notify_flags);
genericpage->ai_info.notify_flags |= AI_NOTIFIES_ALWAYS_ON;
cf_WriteFloat(outfile, genericpage->ai_info.max_delta_turn_rate);
cf_WriteFloat(outfile, genericpage->ai_info.circle_distance);
cf_WriteFloat(outfile, genericpage->ai_info.attack_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.dodge_percent);
cf_WriteFloat(outfile, genericpage->ai_info.dodge_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.flee_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.melee_damage[0]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_damage[1]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_latency[0]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_latency[1]);
for (i=0;i<MAX_OBJ_SOUNDS;i++)
{
cf_WriteByte (outfile,GENERICPAGE_COMMAND_SOUND_NAME);
cf_WriteByte (outfile,strlen (genericpage->sound_name[i])+2); // 1 for sound index, 1 for null term
cf_WriteByte (outfile,i);
cf_WriteString (outfile,genericpage->sound_name[i]);
}
for (i=0;i<MAX_AI_SOUNDS;i++)
{
cf_WriteByte (outfile,GENERICPAGE_COMMAND_AI_SOUND_NAME);
cf_WriteByte (outfile,strlen (genericpage->ai_sound_name[i])+2); // 1 for sound index, 1 for null term
cf_WriteByte (outfile,i);
cf_WriteString (outfile,genericpage->ai_sound_name[i]);
}
for (i = 0; i<MAX_DSPEW_TYPES; i++)
{
cf_WriteByte(outfile,GENERICPAGE_COMMAND_DSPEW_INFO);
cf_WriteByte(outfile, strlen(genericpage->dspew_name[i]) + 9); // 1 for null charactor
cf_WriteByte(outfile, i);
cf_WriteByte(outfile, genericpage->objinfo_struct.f_dspew);
cf_WriteFloat(outfile, genericpage->objinfo_struct.dspew_percent[i]);
cf_WriteShort(outfile, genericpage->objinfo_struct.dspew_number[i]);
cf_WriteString(outfile, genericpage->dspew_name[i]);
}
cf_WriteByte(outfile,GENERICPAGE_COMMAND_AI_INFO2);
cf_WriteByte(outfile,13*sizeof(float));
cf_WriteFloat(outfile, genericpage->ai_info.curiousity);
cf_WriteFloat(outfile, genericpage->ai_info.night_vision);
cf_WriteFloat(outfile, genericpage->ai_info.fog_vision);
cf_WriteFloat(outfile, genericpage->ai_info.lead_accuracy);
cf_WriteFloat(outfile, genericpage->ai_info.lead_varience);
cf_WriteFloat(outfile, genericpage->ai_info.fire_spread);
cf_WriteFloat(outfile, genericpage->ai_info.fight_team);
cf_WriteFloat(outfile, genericpage->ai_info.fight_same);
cf_WriteFloat(outfile, genericpage->ai_info.agression);
cf_WriteFloat(outfile, genericpage->ai_info.hearing);
cf_WriteFloat(outfile, genericpage->ai_info.frustration);
cf_WriteFloat(outfile, genericpage->ai_info.roaming);
cf_WriteFloat(outfile, genericpage->ai_info.life_preservation);
for (i=0;i<NUM_MOVEMENT_CLASSES;i++)
{
int j;
cf_WriteByte (outfile,GENERICPAGE_COMMAND_ANIM_STATES);
size= sizeof(anim_entry) * NUM_ANIMS_PER_CLASS;
size++; // add a byte to tell which class this is for
cf_WriteByte (outfile,size);
cf_WriteByte (outfile,i);
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
cf_WriteShort (outfile, genericpage->anim[i].elem[j].from);
cf_WriteShort (outfile, genericpage->anim[i].elem[j].to);
cf_WriteFloat (outfile, genericpage->anim[i].elem[j].spc);
}
}
cf_WriteByte (outfile,GENERICPAGE_COMMAND_WB_FLAGS);
cf_WriteByte (outfile, sizeof(int) * MAX_WBS_PER_OBJ);
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
cf_WriteByte(outfile, genericpage->static_wb[i].flags);
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
int j;
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WB_INFO);
size = 202;
cf_WriteByte (outfile,size);
cf_WriteByte (outfile,i);
for(j = 0; j < MAX_WB_GUNPOINTS; j++) cf_WriteShort(outfile, genericpage->static_wb[i].gp_weapon_index[j]);
cf_WriteShort(outfile, genericpage->static_wb[i].aiming_gp_index);
cf_WriteByte(outfile, genericpage->static_wb[i].num_masks);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++) cf_WriteByte(outfile, genericpage->static_wb[i].gp_fire_masks[j]);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++) cf_WriteFloat(outfile, genericpage->static_wb[i].gp_fire_wait[j]);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
{
cf_WriteFloat(outfile, genericpage->static_wb[i].anim_time[j]);
cf_WriteFloat(outfile, genericpage->static_wb[i].anim_start_frame[j]);
cf_WriteFloat(outfile, genericpage->static_wb[i].anim_fire_frame[j]);
cf_WriteFloat(outfile, genericpage->static_wb[i].anim_end_frame[j]);
}
cf_WriteByte(outfile, genericpage->static_wb[i].aiming_flags);
cf_WriteFloat(outfile, genericpage->static_wb[i].aiming_3d_dot);
cf_WriteFloat(outfile, genericpage->static_wb[i].aiming_3d_dist);
cf_WriteFloat(outfile, genericpage->static_wb[i].aiming_XZ_dot);
}
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
int j;
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
{
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WB_WEAPON);
size = strlen(genericpage->weapon_name[i][j])+1+2; // 1 for the null charactor and 2 for the 2 indices
cf_WriteByte (outfile,size);
cf_WriteByte (outfile,i);
cf_WriteByte (outfile,j);
cf_WriteString (outfile,genericpage->weapon_name[i][j]);
}
}
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WB_QUADMASK);
cf_WriteByte (outfile, MAX_WBS_PER_OBJ);
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
cf_WriteByte (outfile, genericpage->static_wb[i].gp_quad_fire_mask);
}
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
int j;
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
{
cf_WriteByte (outfile, GENERICPAGE_COMMAND_WB_FIRE_SOUND);
size = strlen(genericpage->fire_sound_name[i][j])+1+2; // 1 for the null charactor and 2 for the 2 indices
cf_WriteByte (outfile,size);
cf_WriteByte (outfile,i);
cf_WriteByte (outfile,j);
cf_WriteString (outfile,genericpage->fire_sound_name[i][j]);
}
}
for(i = 0; i < NUM_MOVEMENT_CLASSES; i++)
{
int j;
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
cf_WriteByte (outfile, GENERICPAGE_COMMAND_ANIM_SOUND_NAME);
size = strlen(genericpage->anim_sound_name[i][j])+1+2; // 1 for the null charactor and 2 for the 2 indices
cf_WriteByte (outfile,size);
cf_WriteByte (outfile,i);
cf_WriteByte (outfile,j);
cf_WriteString (outfile,genericpage->anim_sound_name[i][j]);
}
}
cf_WriteByte (outfile,GENERICPAGE_COMMAND_END); // we're all done
cf_WriteByte (outfile,0);
}
// Given an open file pointer and a generic_page struct, writes that generic page out
void mng_WriteNewGenericPage (CFILE *outfile,mngs_generic_page *genericpage)
{
int i,j;
ASSERT (outfile!=NULL);
ASSERT (genericpage!=NULL);
ASSERT ((strlen(genericpage->image_name))>2);
int offset=StartManagePage (outfile,PAGETYPE_GENERIC);
cf_WriteShort (outfile,GENERICFILE_VERSION);
cf_WriteByte (outfile,genericpage->objinfo_struct.type);
// Write out object name
cf_WriteString (outfile,genericpage->objinfo_struct.name);
// Write out model names
cf_WriteString (outfile,genericpage->image_name);
cf_WriteString (outfile,genericpage->med_image_name);
cf_WriteString (outfile,genericpage->lo_image_name);
// Write out impact data
cf_WriteFloat(outfile, genericpage->objinfo_struct.impact_size);
cf_WriteFloat(outfile, genericpage->objinfo_struct.impact_time);
cf_WriteFloat(outfile, genericpage->objinfo_struct.damage);
// Write score
cf_WriteShort(outfile,genericpage->objinfo_struct.score);
// Write ammo
if (genericpage->objinfo_struct.type == OBJ_POWERUP)
cf_WriteShort(outfile,genericpage->objinfo_struct.ammo_count);
//Write script name
cf_WriteString (outfile,"");//genericpage->objinfo_struct.script_name
//Write module name
cf_WriteString (outfile,genericpage->objinfo_struct.module_name);
//Write scriptname override
cf_WriteString (outfile,genericpage->objinfo_struct.script_name_override);
if (genericpage->objinfo_struct.description!=NULL)
{
// Write description if there is one
cf_WriteByte (outfile,1);
cf_WriteString (outfile,genericpage->objinfo_struct.description);
}
else
cf_WriteByte (outfile,0);
// Write icon name
cf_WriteString (outfile,genericpage->objinfo_struct.icon_name);
// Write LOD distances
cf_WriteFloat (outfile,genericpage->objinfo_struct.med_lod_distance);
cf_WriteFloat (outfile,genericpage->objinfo_struct.lo_lod_distance);
// Write physics stuff
mng_WritePhysicsChunk (&genericpage->objinfo_struct.phys_info,outfile);
// Write size
cf_WriteFloat (outfile,genericpage->objinfo_struct.size);
// Write light info
mng_WriteLightingChunk (&genericpage->objinfo_struct.lighting_info,outfile);
// Write hit points
cf_WriteInt (outfile,genericpage->objinfo_struct.hit_points);
// Write flags
cf_WriteInt (outfile,genericpage->objinfo_struct.flags);
// Write AI info
cf_WriteInt (outfile, genericpage->ai_info.flags);
cf_WriteByte (outfile, genericpage->ai_info.ai_class);
cf_WriteByte (outfile, genericpage->ai_info.ai_type);
cf_WriteByte (outfile, genericpage->ai_info.movement_type);
cf_WriteByte (outfile, genericpage->ai_info.movement_subtype);
cf_WriteFloat(outfile, genericpage->ai_info.fov);
cf_WriteFloat(outfile, genericpage->ai_info.max_velocity);
cf_WriteFloat(outfile, genericpage->ai_info.max_delta_velocity);
cf_WriteFloat(outfile, genericpage->ai_info.max_turn_rate);
// Makes sure there are no bugs as things are added and removed -- ask chris
genericpage->ai_info.notify_flags &= ~AI_NOTIFIES_ALWAYS_ON;
cf_WriteInt (outfile, genericpage->ai_info.notify_flags);
genericpage->ai_info.notify_flags |= AI_NOTIFIES_ALWAYS_ON;
cf_WriteFloat(outfile, genericpage->ai_info.max_delta_turn_rate);
cf_WriteFloat(outfile, genericpage->ai_info.circle_distance);
cf_WriteFloat(outfile, genericpage->ai_info.attack_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.dodge_percent);
cf_WriteFloat(outfile, genericpage->ai_info.dodge_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.flee_vel_percent);
cf_WriteFloat(outfile, genericpage->ai_info.melee_damage[0]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_damage[1]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_latency[0]);
cf_WriteFloat(outfile, genericpage->ai_info.melee_latency[1]);
cf_WriteFloat(outfile, genericpage->ai_info.curiousity);
cf_WriteFloat(outfile, genericpage->ai_info.night_vision);
cf_WriteFloat(outfile, genericpage->ai_info.fog_vision);
cf_WriteFloat(outfile, genericpage->ai_info.lead_accuracy);
cf_WriteFloat(outfile, genericpage->ai_info.lead_varience);
cf_WriteFloat(outfile, genericpage->ai_info.fire_spread);
cf_WriteFloat(outfile, genericpage->ai_info.fight_team);
cf_WriteFloat(outfile, genericpage->ai_info.fight_same);
cf_WriteFloat(outfile, genericpage->ai_info.agression);
cf_WriteFloat(outfile, genericpage->ai_info.hearing);
cf_WriteFloat(outfile, genericpage->ai_info.frustration);
cf_WriteFloat(outfile, genericpage->ai_info.roaming);
cf_WriteFloat(outfile, genericpage->ai_info.life_preservation);
cf_WriteFloat(outfile, genericpage->ai_info.avoid_friends_distance);
cf_WriteFloat(outfile, genericpage->ai_info.biased_flight_importance);
cf_WriteFloat(outfile, genericpage->ai_info.biased_flight_min);
cf_WriteFloat(outfile, genericpage->ai_info.biased_flight_max);
// Write out objects spewed
for (i = 0; i<MAX_DSPEW_TYPES; i++)
{
cf_WriteByte(outfile, genericpage->objinfo_struct.f_dspew);
cf_WriteFloat(outfile, genericpage->objinfo_struct.dspew_percent[i]);
cf_WriteShort(outfile, genericpage->objinfo_struct.dspew_number[i]);
cf_WriteString(outfile, genericpage->dspew_name[i]);
}
// Write out animation info
for (i=0;i<NUM_MOVEMENT_CLASSES;i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
cf_WriteShort (outfile, genericpage->anim[i].elem[j].from);
cf_WriteShort (outfile, genericpage->anim[i].elem[j].to);
cf_WriteFloat (outfile, genericpage->anim[i].elem[j].spc);
}
}
// Write out weapon batteries
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
mng_WriteWeaponBatteryChunk (&genericpage->static_wb[i],outfile);
// Write out weapon names
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
cf_WriteString (outfile,genericpage->weapon_name[i][j]);
}
// Write out sounds
for (i=0;i<MAX_OBJ_SOUNDS;i++)
cf_WriteString (outfile,genericpage->sound_name[i]);
for (i=0;i<MAX_AI_SOUNDS;i++)
cf_WriteString (outfile,genericpage->ai_sound_name[i]);
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
cf_WriteString (outfile,genericpage->fire_sound_name[i][j]);
}
for(i = 0; i < NUM_MOVEMENT_CLASSES; i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
cf_WriteString (outfile,genericpage->anim_sound_name[i][j]);
}
// Write out respawn scalar
cf_WriteFloat (outfile,genericpage->objinfo_struct.respawn_scalar);
//Write out death information
cf_WriteShort(outfile,MAX_DEATH_TYPES);
for (i=0;i<MAX_DEATH_TYPES;i++) {
cf_WriteInt(outfile,genericpage->objinfo_struct.death_types[i].flags);
cf_WriteFloat(outfile,genericpage->objinfo_struct.death_types[i].delay_min);
cf_WriteFloat(outfile,genericpage->objinfo_struct.death_types[i].delay_max);
cf_WriteByte(outfile,genericpage->objinfo_struct.death_probabilities[i]);
}
EndManagePage (outfile,offset);
}
//Old delay types
#define OLD_DF_DELAY_NONE 0x0000000
#define OLD_DF_DELAY_MIN_MAX 0x0000001
#define OLD_DF_DELAY_FROM_ANIM 0x0000002
#define OLD_DF_DELAY_MASK 0x0000003
#define OLD_DF_DELAY_SHIFT 0
void GenericPageSetPowerupDefaultAmmo(object_info *ip)
{
//Default is zero
ip->ammo_count = 0;
//Set for specific types
if (!stricmp(ip->name,"Vauss"))
ip->ammo_count = 5000;
if (!stricmp(ip->name,"Napalm"))
ip->ammo_count = 500;
if (!stricmp(ip->name,"MassDriver"))
ip->ammo_count = 20;
if (!stricmp(ip->name,"Frag"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"ImpactMortar"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"NapalmRocket"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Cyclone"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"BlackShark"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Concussion"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Homing"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Smart"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Mega"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"Guided"))
ip->ammo_count = 1;
if (!stricmp(ip->name,"4PackHoming"))
ip->ammo_count = 4;
if (!stricmp(ip->name,"4PackConc"))
ip->ammo_count = 4;
if (!stricmp(ip->name,"4PackFrag"))
ip->ammo_count = 4;
if (!stricmp(ip->name,"4PackGuided"))
ip->ammo_count = 4;
if (!stricmp(ip->name,"Vauss clip"))
ip->ammo_count = 1250;
if (!stricmp(ip->name,"MassDriverAmmo"))
ip->ammo_count = 5;
if (!stricmp(ip->name,"NapalmTank"))
ip->ammo_count = 100;
}
// Reads a generic page from an open file. Returns 0 on error.
int mng_ReadNewGenericPage (CFILE *infile,mngs_generic_page *genericpage)
{
int i,j;
ASSERT (infile!=NULL);
mng_InitGenericPage (genericpage);
int version=cf_ReadShort (infile);
genericpage->objinfo_struct.type=cf_ReadByte (infile);
// Read object name
cf_ReadString (genericpage->objinfo_struct.name,PAGENAME_LEN,infile);
// Read model names
cf_ReadString (genericpage->image_name,PAGENAME_LEN,infile);
cf_ReadString (genericpage->med_image_name,PAGENAME_LEN,infile);
cf_ReadString (genericpage->lo_image_name,PAGENAME_LEN,infile);
// Read out impact data
genericpage->objinfo_struct.impact_size=cf_ReadFloat (infile);
genericpage->objinfo_struct.impact_time=cf_ReadFloat (infile);
genericpage->objinfo_struct.damage=cf_ReadFloat (infile);
// Read score
if (version >= 24)
genericpage->objinfo_struct.score = cf_ReadShort(infile);
else
genericpage->objinfo_struct.score = cf_ReadByte(infile);
// Read ammo
if (genericpage->objinfo_struct.type == OBJ_POWERUP) {
if (version >= 25)
genericpage->objinfo_struct.ammo_count = cf_ReadShort(infile);
else
GenericPageSetPowerupDefaultAmmo(&genericpage->objinfo_struct);
}
else
genericpage->objinfo_struct.ammo_count = 0;
//Read script name
char dummy[256];
cf_ReadString (dummy,PAGENAME_LEN,infile);//genericpage->objinfo_struct.script_name
if(version>=18)
{
cf_ReadString (genericpage->objinfo_struct.module_name,MAX_MODULENAME_LEN,infile);
#ifdef MACINTOSH //DAJ
char *dot = strchr(genericpage->objinfo_struct.module_name, '.');
if(dot)
strcpy(dot, ".msl");
#endif
}else
{
genericpage->objinfo_struct.module_name[0] = '\0';
}
if(version>=19)
{
cf_ReadString (genericpage->objinfo_struct.script_name_override,PAGENAME_LEN,infile);
}else
{
genericpage->objinfo_struct.script_name_override[0] = '\0';
}
int desc=cf_ReadByte (infile);
if (desc)
{
// Read description if there is one
char tempbuf[1024];
cf_ReadString (tempbuf,1024,infile);
int slen=strlen (tempbuf)+1;
genericpage->objinfo_struct.description=(char *)mem_malloc (slen);
ASSERT (genericpage->objinfo_struct.description);
strcpy (genericpage->objinfo_struct.description,tempbuf);
}
else
genericpage->objinfo_struct.description=NULL;
// Read icon name
cf_ReadString (genericpage->objinfo_struct.icon_name,PAGENAME_LEN,infile);
// Read LOD distances
genericpage->objinfo_struct.med_lod_distance=cf_ReadFloat (infile);
genericpage->objinfo_struct.lo_lod_distance=cf_ReadFloat (infile);
// Read physics stuff
mng_ReadPhysicsChunk (&genericpage->objinfo_struct.phys_info,infile);
// Write size
genericpage->objinfo_struct.size=cf_ReadFloat(infile);
// Write light info
mng_ReadLightingChunk (&genericpage->objinfo_struct.lighting_info,infile);
// Read hit points
genericpage->objinfo_struct.hit_points=cf_ReadInt(infile);
// Read flags
genericpage->objinfo_struct.flags=cf_ReadInt (infile);
// Write AI info
genericpage->ai_info.flags=cf_ReadInt(infile);
genericpage->ai_info.ai_class=cf_ReadByte (infile);
genericpage->ai_info.ai_type=cf_ReadByte (infile);
genericpage->ai_info.movement_type=cf_ReadByte (infile);
genericpage->ai_info.movement_subtype=cf_ReadByte (infile);
genericpage->ai_info.fov=cf_ReadFloat (infile);
genericpage->ai_info.max_velocity=cf_ReadFloat (infile);
genericpage->ai_info.max_delta_velocity=cf_ReadFloat (infile);
genericpage->ai_info.max_turn_rate=cf_ReadFloat (infile);
// Makes sure there are no bugs as things are added and removed -- ask chris
genericpage->ai_info.notify_flags &= ~AI_NOTIFIES_ALWAYS_ON;
genericpage->ai_info.notify_flags=cf_ReadInt(infile);
genericpage->ai_info.notify_flags |= AI_NOTIFIES_ALWAYS_ON;
genericpage->ai_info.max_delta_turn_rate=cf_ReadFloat (infile);
genericpage->ai_info.circle_distance=cf_ReadFloat (infile);
genericpage->ai_info.attack_vel_percent=cf_ReadFloat (infile);
genericpage->ai_info.dodge_percent=cf_ReadFloat (infile);
genericpage->ai_info.dodge_vel_percent=cf_ReadFloat (infile);
genericpage->ai_info.flee_vel_percent=cf_ReadFloat (infile);
genericpage->ai_info.melee_damage[0]=cf_ReadFloat (infile);
genericpage->ai_info.melee_damage[1]=cf_ReadFloat (infile);
genericpage->ai_info.melee_latency[0]=cf_ReadFloat (infile);
genericpage->ai_info.melee_latency[1]=cf_ReadFloat (infile);
genericpage->ai_info.curiousity=cf_ReadFloat (infile);
genericpage->ai_info.night_vision=cf_ReadFloat (infile);
genericpage->ai_info.fog_vision=cf_ReadFloat (infile);
genericpage->ai_info.lead_accuracy=cf_ReadFloat (infile);
genericpage->ai_info.lead_varience=cf_ReadFloat (infile);
genericpage->ai_info.fire_spread=cf_ReadFloat (infile);
genericpage->ai_info.fight_team=cf_ReadFloat (infile);
genericpage->ai_info.fight_same=cf_ReadFloat (infile);
genericpage->ai_info.agression=cf_ReadFloat (infile);
genericpage->ai_info.hearing=cf_ReadFloat (infile);
genericpage->ai_info.frustration=cf_ReadFloat (infile);
genericpage->ai_info.roaming=cf_ReadFloat (infile);
genericpage->ai_info.life_preservation=cf_ReadFloat (infile);
if(version >= 16)
{
genericpage->ai_info.avoid_friends_distance =cf_ReadFloat (infile);
}
else if((genericpage->objinfo_struct.flags | OIF_USES_PHYSICS) &&
genericpage->ai_info.max_velocity > 0.0f)
{
genericpage->ai_info.flags |= AIF_AUTO_AVOID_FRIENDS;
genericpage->ai_info.avoid_friends_distance = genericpage->ai_info.circle_distance / 10.f;
if(genericpage->ai_info.avoid_friends_distance < 4.0f)
genericpage->ai_info.avoid_friends_distance = 4.0f;
}
else
{
genericpage->ai_info.avoid_friends_distance = 4.0f;
}
if(version >= 17)
{
genericpage->ai_info.biased_flight_importance = cf_ReadFloat(infile);
genericpage->ai_info.biased_flight_min = cf_ReadFloat(infile);
genericpage->ai_info.biased_flight_max = cf_ReadFloat(infile);
}
else
{
genericpage->ai_info.biased_flight_importance = .5f;
genericpage->ai_info.biased_flight_min = 10.0f;
genericpage->ai_info.biased_flight_max = 50.0f;
}
// Write out objects spewed
for (i = 0; i<MAX_DSPEW_TYPES; i++)
{
genericpage->objinfo_struct.f_dspew=cf_ReadByte (infile);
genericpage->objinfo_struct.dspew_percent[i]=cf_ReadFloat (infile);
genericpage->objinfo_struct.dspew_number[i]=cf_ReadShort (infile);
// Read spew name
cf_ReadString (genericpage->dspew_name[i],PAGENAME_LEN,infile);
}
// Read out animation info
for (i=0;i<NUM_MOVEMENT_CLASSES;i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
if(version < 20)
{
genericpage->anim[i].elem[j].from=cf_ReadByte (infile);
genericpage->anim[i].elem[j].to=cf_ReadByte(infile);
}
else
{
genericpage->anim[i].elem[j].from=cf_ReadShort(infile);
genericpage->anim[i].elem[j].to=cf_ReadShort(infile);
}
genericpage->anim[i].elem[j].spc=cf_ReadFloat (infile);
}
}
// read weapon batteries
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
if (version>=15)
mng_ReadWeaponBatteryChunk (&genericpage->static_wb[i],infile,2);
else
mng_ReadWeaponBatteryChunk (&genericpage->static_wb[i],infile,1);
}
// read weapon names
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
cf_ReadString (genericpage->weapon_name[i][j],PAGENAME_LEN,infile);
}
// read sounds
ASSERT(MAX_OBJ_SOUNDS == 2);
for (i=0;i<MAX_OBJ_SOUNDS;i++)
cf_ReadString (genericpage->sound_name[i],PAGENAME_LEN,infile);
if (version < 26) { //used to be three sounds
char temp_sound_name[PAGENAME_LEN];
cf_ReadString (temp_sound_name,PAGENAME_LEN,infile);
}
for (i=0;i<MAX_AI_SOUNDS;i++)
cf_ReadString (genericpage->ai_sound_name[i],PAGENAME_LEN,infile);
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
cf_ReadString (genericpage->fire_sound_name[i][j],PAGENAME_LEN,infile);
}
for(i = 0; i < NUM_MOVEMENT_CLASSES; i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
cf_ReadString (genericpage->anim_sound_name[i][j],PAGENAME_LEN,infile);
}
// Read respawn scalar
if (version>=21)
genericpage->objinfo_struct.respawn_scalar=cf_ReadFloat (infile);
else
genericpage->objinfo_struct.respawn_scalar=1.0;
if (version >= 22) {
int n_death_types = cf_ReadShort(infile);
for (i=0;i<n_death_types;i++) {
int flags = cf_ReadInt(infile);
if (version == 22) { //translate death flags
Int3(); //this version no longer supported
}
genericpage->objinfo_struct.death_types[i].flags = flags;
genericpage->objinfo_struct.death_types[i].delay_min = cf_ReadFloat(infile);
genericpage->objinfo_struct.death_types[i].delay_max = cf_ReadFloat(infile);
genericpage->objinfo_struct.death_probabilities[i] = cf_ReadByte(infile);
//Fix up for changed flags
if (version < 27) {
if ((flags & OLD_DF_DELAY_MASK) != OLD_DF_DELAY_MIN_MAX) {
genericpage->objinfo_struct.death_types[i].delay_min = 0.0;
genericpage->objinfo_struct.death_types[i].delay_max = 0.0;
}
flags &= ~DF_UNUSED;
}
}
}
//Set score from hitpoints if old version
if (version < 24) {
if ((genericpage->objinfo_struct.type == OBJ_ROBOT) || (genericpage->objinfo_struct.type == OBJ_BUILDING && (genericpage->objinfo_struct.flags & OIF_CONTROL_AI)))
if (genericpage->objinfo_struct.flags & OIF_DESTROYABLE)
genericpage->objinfo_struct.score = 3 * genericpage->objinfo_struct.hit_points;
}
ASSERT(genericpage->objinfo_struct.type != OBJ_NONE);
return 1; // successfully read
}
// Reads a generic page from an open file. Returns 0 on error.
int mng_ReadGenericPage (CFILE *infile,mngs_generic_page *genericpage)
{
int done=0;
char command;
ushort len;
int i,temp,version,t;
if (!Old_table_method)
return mng_ReadNewGenericPage (infile,genericpage);
ASSERT (infile!=NULL);
mng_InitGenericPage (genericpage);
while (!done)
{
// Read in command byte then read in the length of that commands data
command=cf_ReadByte (infile);
len=cf_ReadByte(infile);
switch (command)
{
case GENERICPAGE_COMMAND_END:
done=1;
break;
case GENERICPAGE_COMMAND_VERSION:
version = cf_ReadByte(infile);
break;
case GENERICPAGE_COMMAND_TYPE:
genericpage->objinfo_struct.type = cf_ReadByte(infile);
break;
case GENERICPAGE_COMMAND_SCORE:
genericpage->objinfo_struct.score = cf_ReadByte(infile);
break;
case GENERICPAGE_COMMAND_SCRIPT: // Obsolete as of 09-24-97
cf_ReadByte(infile);
break;
case GENERICPAGE_COMMAND_SCRIPTNAME:
{
char dummy[256];
cf_ReadString(dummy, len+1, infile);//genericpage->objinfo_struct.script_name
}break;
case GENERICPAGE_COMMAND_DESCRIPTION:
genericpage->objinfo_struct.description=(char *)mem_malloc (len+1);
ASSERT (genericpage->objinfo_struct.description); // out of memory!
cf_ReadString(genericpage->objinfo_struct.description, len+1, infile);
break;
case GENERICPAGE_COMMAND_ICON_NAME:
cf_ReadString(genericpage->objinfo_struct.icon_name, len+1, infile);
break;
case GENERICPAGE_COMMAND_IMAGE_NAME: // the name of the generic model
cf_ReadString (genericpage->image_name,len+1,infile);
break;
case GENERICPAGE_COMMAND_LOD_MODELS: // the name of the lower res models
cf_ReadString (genericpage->med_image_name,len+1,infile);
cf_ReadString (genericpage->lo_image_name,len+1,infile);
break;
case GENERICPAGE_COMMAND_NAME:
cf_ReadString (genericpage->objinfo_struct.name,len+1,infile);
break;
case GENERICPAGE_COMMAND_SIZE:
genericpage->objinfo_struct.size=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_LOD_DISTANCE:
genericpage->objinfo_struct.med_lod_distance=cf_ReadFloat(infile);
genericpage->objinfo_struct.lo_lod_distance=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_DSPEW_INFO:
{
int i = cf_ReadByte(infile);
genericpage->objinfo_struct.f_dspew = cf_ReadByte(infile);
genericpage->objinfo_struct.dspew_percent[i] = cf_ReadFloat(infile);
genericpage->objinfo_struct.dspew_number[i] = cf_ReadShort(infile);
cf_ReadString (genericpage->dspew_name[i],len-7,infile);
}
break;
case GENERICPAGE_COMMAND_WB_FLAGS:
{
for (int i=0;i<MAX_WBS_PER_OBJ;i++)
genericpage->static_wb[i].flags=cf_ReadByte (infile);
}
break;
case GENERICPAGE_COMMAND_IMPACT:
genericpage->objinfo_struct.impact_size = cf_ReadFloat(infile);
genericpage->objinfo_struct.impact_time = cf_ReadFloat(infile);
genericpage->objinfo_struct.damage = cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_FLICKER_DISTANCE:
genericpage->objinfo_struct.lighting_info.flicker_distance=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_DIRECTION_DOT:
genericpage->objinfo_struct.lighting_info.directional_dot=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_AI_INFO2:
genericpage->ai_info.curiousity=cf_ReadFloat(infile);
genericpage->ai_info.night_vision=cf_ReadFloat(infile);
genericpage->ai_info.fog_vision=cf_ReadFloat(infile);
genericpage->ai_info.lead_accuracy=cf_ReadFloat(infile);
genericpage->ai_info.lead_varience=cf_ReadFloat(infile);
genericpage->ai_info.fire_spread=cf_ReadFloat(infile);
genericpage->ai_info.fight_team=cf_ReadFloat(infile);
genericpage->ai_info.fight_same=cf_ReadFloat(infile);
genericpage->ai_info.agression=cf_ReadFloat(infile);
genericpage->ai_info.hearing=cf_ReadFloat(infile);
genericpage->ai_info.frustration=cf_ReadFloat(infile);
genericpage->ai_info.roaming=cf_ReadFloat(infile);
genericpage->ai_info.life_preservation=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_LIGHT_CAST:
genericpage->objinfo_struct.lighting_info.light_distance=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.red_light1=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.green_light1=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.blue_light1=cf_ReadFloat(infile);
if (version>=2)
genericpage->objinfo_struct.lighting_info.time_interval=cf_ReadFloat(infile);
if (version>=3)
{
genericpage->objinfo_struct.lighting_info.red_light2=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.green_light2=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.blue_light2=cf_ReadFloat(infile);
genericpage->objinfo_struct.lighting_info.flags=cf_ReadInt(infile);
genericpage->objinfo_struct.lighting_info.timebits=cf_ReadInt(infile);
genericpage->objinfo_struct.lighting_info.angle=cf_ReadByte(infile);
}
if (version>=5)
{
genericpage->objinfo_struct.lighting_info.lighting_render_type=cf_ReadByte(infile);
}
else
genericpage->objinfo_struct.lighting_info.lighting_render_type=LRT_STATIC;
break;
case GENERICPAGE_COMMAND_HITPOINTS:
genericpage->objinfo_struct.hit_points = cf_ReadInt(infile);
break;
case GENERICPAGE_COMMAND_PHYS_MASS:
genericpage->objinfo_struct.phys_info.mass=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_PHYS_DRAG:
genericpage->objinfo_struct.phys_info.drag=cf_ReadFloat(infile);
break;
case GENERICPAGE_COMMAND_ANIM_STATES:
temp=cf_ReadByte (infile);
{
int j;
for(j = 0; j < NUM_ANIMS_PER_CLASS;j++)
{
if(version < 20)
{
genericpage->anim[temp].elem[j].from = cf_ReadByte(infile);
genericpage->anim[temp].elem[j].to = cf_ReadByte(infile);
}
else
{
genericpage->anim[temp].elem[j].from = cf_ReadShort(infile);
genericpage->anim[temp].elem[j].to = cf_ReadShort(infile);
}
if(version <= 3)
genericpage->anim[temp].elem[j].spc = 1.0f;
else
genericpage->anim[temp].elem[j].spc = cf_ReadFloat(infile);
}
}
break;
case GENERICPAGE_COMMAND_FLAGS:
{
int t = cf_ReadInt(infile);
genericpage->objinfo_struct.flags = t;
break;
}
case GENERICPAGE_COMMAND_WB_INFO:
{
int i,j;
i = cf_ReadByte(infile);
if(version <= 7)
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++) genericpage->static_wb[i].gp_weapon_index[j] = cf_ReadInt(infile);
genericpage->static_wb[i].aiming_gp_index = cf_ReadInt(infile);
}
else
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++) genericpage->static_wb[i].gp_weapon_index[j] = cf_ReadShort(infile);
genericpage->static_wb[i].aiming_gp_index = cf_ReadShort(infile);
}
genericpage->static_wb[i].num_masks = cf_ReadByte(infile);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++) genericpage->static_wb[i].gp_fire_masks[j] = cf_ReadByte(infile);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++) genericpage->static_wb[i].gp_fire_wait[j] = cf_ReadFloat(infile);
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
{
if(version < 12)
{
genericpage->static_wb[i].anim_time[j] = 0.0f;
genericpage->static_wb[i].anim_start_frame[j] = 0.0f;
genericpage->static_wb[i].anim_fire_frame[j] = 0.0f;
genericpage->static_wb[i].anim_end_frame[j] = 0.0f;
}
else
{
genericpage->static_wb[i].anim_time[j] = cf_ReadFloat(infile);
genericpage->static_wb[i].anim_start_frame[j] = cf_ReadFloat(infile);
genericpage->static_wb[i].anim_fire_frame[j] = cf_ReadFloat(infile);
genericpage->static_wb[i].anim_end_frame[j] = cf_ReadFloat(infile);
}
}
genericpage->static_wb[i].aiming_flags = cf_ReadByte(infile);
genericpage->static_wb[i].aiming_3d_dot = cf_ReadFloat(infile);
genericpage->static_wb[i].aiming_3d_dist = cf_ReadFloat(infile);
genericpage->static_wb[i].aiming_XZ_dot = cf_ReadFloat(infile);
break;
}
case GENERICPAGE_COMMAND_WB_QUADMASK:
{
for(int i = 0; i < MAX_WBS_PER_OBJ; i++)
{
genericpage->static_wb[i].gp_quad_fire_mask = cf_ReadByte(infile);
}
break;
}
case GENERICPAGE_COMMAND_WB_WEAPON:
{
int i,j;
i = cf_ReadByte (infile);
j = cf_ReadByte (infile);
cf_ReadString (genericpage->weapon_name[i][j],len-1,infile);
break;
}
case GENERICPAGE_COMMAND_WB_FIRE_SOUND:
{
int i,j;
i = cf_ReadByte (infile);
j = cf_ReadByte (infile);
cf_ReadString (genericpage->fire_sound_name[i][j],len-1,infile);
break;
}
case GENERICPAGE_COMMAND_ANIM_SOUND_NAME:
{
int i,j;
i = cf_ReadByte (infile);
j = cf_ReadByte (infile);
cf_ReadString (genericpage->anim_sound_name[i][j],len-1,infile);
break;
}
case GENERICPAGE_COMMAND_SOUND_NAME:
{
int i;
i = cf_ReadByte (infile);
cf_ReadString (genericpage->sound_name[i],len,infile);
break;
}
case GENERICPAGE_COMMAND_AI_SOUND_NAME:
{
int i;
i = cf_ReadByte (infile);
cf_ReadString (genericpage->ai_sound_name[i],len,infile);
break;
}
case GENERICPAGE_COMMAND_AI_INFO:
if(version <= 6)
{
genericpage->ai_info.flags=cf_ReadInt(infile);
}
else
{
// Makes sure there are no bugs as things are added and removed -- ask chris
genericpage->ai_info.notify_flags = AI_NOTIFIES_ALWAYS_ON;
genericpage->ai_info.flags=cf_ReadInt(infile);
genericpage->ai_info.ai_class=cf_ReadByte(infile);
genericpage->ai_info.ai_type=cf_ReadByte(infile);
if(version < 13)
cf_ReadInt(infile);
genericpage->ai_info.movement_type=cf_ReadByte(infile);
genericpage->ai_info.movement_subtype=cf_ReadByte(infile);
genericpage->ai_info.fov=cf_ReadFloat(infile);
if(version >= 10)
{
genericpage->ai_info.max_velocity=cf_ReadFloat(infile);
genericpage->ai_info.max_delta_velocity=cf_ReadFloat(infile);
genericpage->ai_info.max_turn_rate=cf_ReadFloat(infile);
// Makes sure there are no bugs as things are added and removed -- ask chris
genericpage->ai_info.notify_flags|=cf_ReadInt(infile);
}
if(version >= 11)
{
genericpage->ai_info.max_delta_turn_rate=cf_ReadFloat(infile);
genericpage->ai_info.circle_distance=cf_ReadFloat(infile);
genericpage->ai_info.attack_vel_percent=cf_ReadFloat(infile);
genericpage->ai_info.dodge_percent=cf_ReadFloat(infile);
genericpage->ai_info.dodge_vel_percent=cf_ReadFloat(infile);
genericpage->ai_info.flee_vel_percent=cf_ReadFloat(infile);
genericpage->ai_info.melee_damage[0]=cf_ReadFloat(infile);
genericpage->ai_info.melee_damage[1]=cf_ReadFloat(infile);
genericpage->ai_info.melee_latency[0]=cf_ReadFloat(infile);
genericpage->ai_info.melee_latency[1]=cf_ReadFloat(infile);
}
else
{
genericpage->ai_info.max_delta_turn_rate = 16000.0;
genericpage->ai_info.circle_distance = 10.0f;
genericpage->ai_info.attack_vel_percent = 1.0f;
genericpage->ai_info.dodge_percent = .4f;
genericpage->ai_info.dodge_vel_percent = .5f;
genericpage->ai_info.flee_vel_percent = 1.0f;
genericpage->ai_info.melee_damage[0] = 9.0f;
genericpage->ai_info.melee_damage[1] = 13.0f;
genericpage->ai_info.melee_latency[0] = 3.1f;
genericpage->ai_info.melee_latency[1] = 4.5f;
}
if(version >= 16)
{
genericpage->ai_info.avoid_friends_distance = cf_ReadFloat(infile);
}
}
break;
case GENERICPAGE_COMMAND_PHYS_FLAGS:
genericpage->objinfo_struct.phys_info.flags=cf_ReadInt(infile);
break;
case GENERICPAGE_COMMAND_ROT_DRAG:
genericpage->objinfo_struct.phys_info.rotdrag=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_FULL_THRUST:
genericpage->objinfo_struct.phys_info.full_thrust=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_FULL_ROTTHRUST:
genericpage->objinfo_struct.phys_info.full_rotthrust=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_TURNROLL_RATE:
genericpage->objinfo_struct.phys_info.max_turnroll_rate=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_TURNROLL_RATIO:
genericpage->objinfo_struct.phys_info.turnroll_ratio=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_WIGGLE_AMP:
genericpage->objinfo_struct.phys_info.wiggle_amplitude=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_WIGGLE_FREQ:
genericpage->objinfo_struct.phys_info.wiggles_per_sec=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_INT_VELOCITY:
genericpage->objinfo_struct.phys_info.velocity.z=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_INT_ROTVEL:
genericpage->objinfo_struct.phys_info.rotvel.x=cf_ReadFloat (infile);
genericpage->objinfo_struct.phys_info.rotvel.y=cf_ReadFloat (infile);
genericpage->objinfo_struct.phys_info.rotvel.z=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_NUM_BOUNCES:
genericpage->objinfo_struct.phys_info.num_bounces=cf_ReadInt (infile);
break;
case GENERICPAGE_COMMAND_COEFF_REST:
genericpage->objinfo_struct.phys_info.coeff_restitution=cf_ReadFloat (infile);
break;
case GENERICPAGE_COMMAND_HIT_DIE_DOT:
genericpage->objinfo_struct.phys_info.hit_die_dot=cf_ReadFloat (infile);
break;
default:
// Ignore the ones we don't know
for (i=0;i<len;i++)
cf_ReadByte (infile);
break;
}
}
ASSERT(genericpage->objinfo_struct.type != OBJ_NONE);
if(version < 16)
{
genericpage->ai_info.flags |= AIF_AUTO_AVOID_FRIENDS;
genericpage->ai_info.avoid_friends_distance = genericpage->ai_info.circle_distance / 10.f;
if(genericpage->ai_info.avoid_friends_distance < 4.0f)
genericpage->ai_info.avoid_friends_distance = 4.0f;
}
if (!strnicmp ("INVALID",genericpage->med_image_name,7))
strcpy (genericpage->med_image_name,"");
if (!strnicmp ("INVALID",genericpage->lo_image_name,7))
strcpy (genericpage->lo_image_name,"");
for (i=0;i<MAX_OBJ_SOUNDS;i++)
{
if (!strnicmp ("INVALID",genericpage->sound_name[i],7))
strcpy (genericpage->sound_name[i],"");
}
for (i=0;i<MAX_DSPEW_TYPES;i++)
{
if (!strnicmp ("INVALID",genericpage->dspew_name[i],7))
strcpy (genericpage->dspew_name[i],"");
}
for (i=0;i<MAX_AI_SOUNDS;i++)
{
if (!strnicmp ("INVALID",genericpage->ai_sound_name[i],7))
strcpy (genericpage->ai_sound_name[i],"");
}
for (i=0;i<MAX_WBS_PER_OBJ;i++)
{
for (t=0;t<MAX_WB_FIRING_MASKS;t++)
{
if (!strnicmp ("INVALID",genericpage->fire_sound_name[i][t],7))
strcpy (genericpage->fire_sound_name[i][t],"");
}
}
for (i=0;i<NUM_MOVEMENT_CLASSES;i++)
{
for (t=0;t<NUM_ANIMS_PER_CLASS;t++)
{
if (!strnicmp ("INVALID",genericpage->anim_sound_name[i][t],7))
strcpy (genericpage->anim_sound_name[i][t],"");
}
}
return 1; // successfully read
}
// Reads in the generic named "name" into genericpage struct
// Returns 0 on error or couldn't find, else 1 if all is good
int mng_FindSpecificGenericPage (char *name,mngs_generic_page *genericpage,int offset)
{
CFILE *infile;
ubyte pagetype;
int done=0,found=0;
int first_try=1;
char tablename[TABLE_NAME_LEN];
if (Loading_locals)
{
infile=cfopen (LocalTableFilename,"rb");
}
else if (Loading_addon_table!=-1)
{
infile=cfopen (AddOnDataTables[Loading_addon_table].AddOnTableFilename,"rb");
}
else
{
if (Network_up && Starting_editor)
{
int farg=FindArg("-filter");
if (farg)
strcpy (tablename,GameArgs[farg+1]);
else
ddio_MakePath (tablename,LocalTableDir,NET_TABLE,NULL);
infile=cfopen (tablename,"rb");
}
else
{
infile = NULL;
if(TablefileNameOverride)
{
infile=cfopen(TablefileNameOverride,"rb");
}
if(!infile)
infile=cfopen (TableFilename,"rb");
}
}
if (!infile)
{
mprintf ((0,"Couldn't open table file to find generic!\n"));
Int3();
return 0;
}
try_again:;
if (offset)
cfseek (infile,offset,SEEK_SET);
// Read in the entire page file until we find the page we want
while (!done)
{
if (cfeof (infile))
{
done=1;
continue;
}
pagetype=cf_ReadByte (infile);
int len=cf_ReadInt(infile);
// If not a generic page, just read it in and ignore it
if (pagetype!=PAGETYPE_GENERIC)
{
cfseek (infile,len-4,SEEK_CUR);
continue;
}
mng_ReadNewGenericPage (infile,genericpage);
if (!stricmp(name,genericpage->objinfo_struct.name))
{
// This is the page we want
found=1;
done=1;
}
else
{
if (genericpage->objinfo_struct.description!=NULL)
{
mem_free (genericpage->objinfo_struct.description);
genericpage->objinfo_struct.description = NULL;
}
genericpage->objinfo_struct.icon_name[0] = '\0';
}
}
cfclose (infile);
if (!found && first_try) {
done = first_try = 0;
infile=cfopen ("extra.gam","rb");
if (infile)
goto try_again;
}
return found; // successful!
}
// Given a generic page, allocs a generic and calls AssignGenericPageTogeneric to actually
// load models and values. Rturns generic handle on success, -1 if fail
int mng_SetAndLoadGeneric (mngs_generic_page *genericpage,CFILE *infile)
{
int i, j, n;
bool f_anim = false;
bool f_weapons = false;
bool f_ai = false;
f_ai = (genericpage->objinfo_struct.flags & OIF_CONTROL_AI)?true:false;
if(f_ai)
{
f_weapons = f_anim = true;
}else
{
if(genericpage->objinfo_struct.type == OBJ_ROBOT || genericpage->objinfo_struct.type == OBJ_BUILDING) {
f_anim = true;
}
else if(genericpage->objinfo_struct.type == OBJ_POWERUP) {
if(f_ai) {
f_anim = true;
} else {
for (i=0;i<NUM_MOVEMENT_CLASSES;i++) {
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++) {
if(genericpage->anim[i].elem[j].to != 0 || genericpage->anim[i].elem[j].from != 0) {
f_anim = true;
break;
}
}
}
}
}
else if(genericpage->objinfo_struct.type == OBJ_CLUTTER) {
if(f_ai) {
f_anim = true;
} else {
for (i=0;i<NUM_MOVEMENT_CLASSES;i++) {
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++) {
if(genericpage->anim[i].elem[j].to != 0 || genericpage->anim[i].elem[j].from != 0) {
f_anim = true;
break;
}
}
}
}
}
for(i = 0; i < MAX_WBS_PER_OBJ; i++) {
for(j = 0; j < genericpage->static_wb[i].num_masks; j++) {
if( genericpage->static_wb[i].gp_fire_masks[j] != 0) {
f_weapons = true;
break;
}
}
}
}
if(Running_editor)
{
f_ai = f_weapons = f_anim = true;
}
n=AllocObjectID(genericpage->objinfo_struct.type,f_anim,f_weapons,f_ai);
if (n<0)
return -1;
if (!mng_AssignGenericPageToObjInfo(genericpage,n,infile))
return -1;
return n;
}
// Given a genericpage and a generic handle, attempts to make generic n correspond to
// to the genericpage.
// Returns 1 on success, 0 otherwise
int mng_AssignGenericPageToObjInfo(mngs_generic_page *genericpage,int n,CFILE *infile)
{
object_info *objinfopointer=&Object_info[n];
int img_handle;
int i, j;
// copy our values
// memcpy (objinfopointer,&genericpage->objinfo_struct,sizeof(*objinfopointer));
memcpy (objinfopointer,&genericpage->objinfo_struct,sizeof(*objinfopointer)-sizeof(anim_elem *)-sizeof(otype_wb_info *)-sizeof(t_ai_info *));
strcpy (objinfopointer->name,genericpage->objinfo_struct.name);
if(objinfopointer->anim)
memcpy(objinfopointer->anim,&genericpage->anim,sizeof(genericpage->anim));
if(objinfopointer->static_wb)
memcpy(objinfopointer->static_wb,&genericpage->static_wb,sizeof(genericpage->static_wb));
if(objinfopointer->ai_info)
memcpy(objinfopointer->ai_info,&genericpage->ai_info,sizeof(genericpage->ai_info));
objinfopointer->multi_allowed = 1;
//since the description pointer was just copied over, no need to malloc mem, copy and then free old, just move ptr
genericpage->objinfo_struct.description = NULL;
strcpy(objinfopointer->icon_name,genericpage->objinfo_struct.icon_name);
// First see if our image differs from the one on the net
// If it is, make a copy
// If its a release version, don't do any of this
#ifndef RELEASE
if (Network_up)
{
char str[200];
char netstr[200];
ddio_MakePath (str,LocalModelsDir,genericpage->image_name,NULL);
ddio_MakePath (netstr,NetModelsDir,genericpage->image_name,NULL);
UpdatePrimitive (str,netstr,genericpage->image_name,PAGETYPE_GENERIC,objinfopointer->name);
if (stricmp (genericpage->med_image_name,"INVALID NAME") && genericpage->med_image_name[0]!=0)
{
ddio_MakePath (str,LocalModelsDir,genericpage->med_image_name,NULL);
ddio_MakePath (netstr,NetModelsDir,genericpage->med_image_name,NULL);
UpdatePrimitive (str,netstr,genericpage->med_image_name,PAGETYPE_GENERIC,objinfopointer->name);
}
if (stricmp (genericpage->lo_image_name,"INVALID NAME") && genericpage->lo_image_name[0]!=0)
{
ddio_MakePath (str,LocalModelsDir,genericpage->lo_image_name,NULL);
ddio_MakePath (netstr,NetModelsDir,genericpage->lo_image_name,NULL);
UpdatePrimitive (str,netstr,genericpage->lo_image_name,PAGETYPE_GENERIC,objinfopointer->name);
}
}
#endif
// Try and load our generic model from the disk
img_handle=LoadPolyModel (genericpage->image_name,1);
if (img_handle<0)
{
mprintf ((0,"Couldn't load file '%s' in AssignGenericPage...\n",genericpage->image_name));
objinfopointer->render_handle=-1;
return 0;
}
else
objinfopointer->render_handle=img_handle;
if (stricmp (genericpage->med_image_name,"INVALID NAME") && genericpage->med_image_name[0]!=0)
{
img_handle=LoadPolyModel (genericpage->med_image_name,1);
if (img_handle<0)
{
mprintf ((0,"Couldn't load file '%s' in AssignGenericPage...\n",genericpage->med_image_name));
objinfopointer->med_render_handle=-1;
return 0;
}
else
objinfopointer->med_render_handle=img_handle;
}
else
objinfopointer->med_render_handle=-1;
if (stricmp (genericpage->lo_image_name,"INVALID NAME") && genericpage->lo_image_name[0]!=0)
{
img_handle=LoadPolyModel (genericpage->lo_image_name,1);
if (img_handle<0)
{
mprintf ((0,"Couldn't load file '%s' in AssignGenericPage...\n",genericpage->lo_image_name));
objinfopointer->lo_render_handle=-1;
return 0;
}
else
objinfopointer->lo_render_handle=img_handle;
}
else
objinfopointer->lo_render_handle=-1;
// Try and load the various sounds
for (i=0;i<MAX_OBJ_SOUNDS;i++)
{
if (stricmp (genericpage->sound_name[i],"INVALID NAME") && genericpage->sound_name[i][0]!=0)
{
int sound_handle=mng_GetGuaranteedSoundPage (genericpage->sound_name[i]);
if (sound_handle<0)
{
mprintf ((0,"Couldn't load sound file '%s' in AssignPowPage %s...\n",genericpage->sound_name[i],genericpage->objinfo_struct.name));
objinfopointer->sounds[i]=SOUND_NONE_INDEX;
}
else
objinfopointer->sounds[i]=sound_handle;
}
else
objinfopointer->sounds[i]=SOUND_NONE_INDEX;
}
for(i=0;i<MAX_DSPEW_TYPES;i++)
{
if(genericpage->dspew_name[i][0] != '\0')
{
int obj_handle = mng_GetGuaranteedGenericPage(genericpage->dspew_name[i], infile);
if(obj_handle < 0)
{
objinfopointer->dspew[i] = 0;
objinfopointer->dspew_number[i] = 0;
objinfopointer->dspew_percent[i] = 0.0f;
}
else
{
objinfopointer->dspew[i] = obj_handle;
}
}
else
{
objinfopointer->dspew[i] = -1;
objinfopointer->dspew_number[i] = 0;
objinfopointer->dspew_percent[i] = 0.0f;
}
}
// Try and load the various sounds
if(objinfopointer->ai_info) {
for (i=0;i<MAX_AI_SOUNDS;i++)
{
if (stricmp (genericpage->ai_sound_name[i],"INVALID NAME") && genericpage->ai_sound_name[i][0]!=0)
{
int sound_handle=mng_GetGuaranteedSoundPage (genericpage->ai_sound_name[i]);
if (sound_handle<0)
{
mprintf ((0,"Couldn't load ai sound file '%s' in AssignPowPage %s...\n",genericpage->ai_sound_name[i],genericpage->objinfo_struct.name));
objinfopointer->ai_info->sound[i]=SOUND_NONE_INDEX;
}
else
objinfopointer->ai_info->sound[i]=sound_handle;
}
else
objinfopointer->ai_info->sound[i]=SOUND_NONE_INDEX;
}
}
// Try and load the various weapons
if(objinfopointer->static_wb) {
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
{
if(genericpage->weapon_name[i][j][0] != '\0')
{
int weapon_handle = mng_GetGuaranteedWeaponPage (genericpage->weapon_name[i][j]);
if (weapon_handle < 0)
{
mprintf ((0,"Couldn't load weapon file '%s' in AssignPowPage %s...\n",genericpage->weapon_name[i][j],genericpage->objinfo_struct.name));
objinfopointer->static_wb[i].gp_weapon_index[j] = LASER_INDEX;
}
else
objinfopointer->static_wb[i].gp_weapon_index[j] = weapon_handle;
}
else
objinfopointer->static_wb[i].gp_weapon_index[j] = LASER_INDEX;
}
}
// Try and load the various wb sounds
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
{
if(genericpage->fire_sound_name[i][j][0] != '\0')
{
int fire_sound_handle = mng_GetGuaranteedSoundPage (genericpage->fire_sound_name[i][j]);
if (fire_sound_handle < 0)
{
mprintf ((0,"Couldn't load fire sound file '%s' in AssignPowPage %s...\n",genericpage->fire_sound_name[i][j],genericpage->objinfo_struct.name));
objinfopointer->static_wb[i].fm_fire_sound_index[j] = SOUND_NONE_INDEX;
}
else
objinfopointer->static_wb[i].fm_fire_sound_index[j] = fire_sound_handle;
}
else
objinfopointer->static_wb[i].fm_fire_sound_index[j] = SOUND_NONE_INDEX;
}
}
}
// Try and load the various wb sounds
if(objinfopointer->anim) {
for(i = 0; i < NUM_MOVEMENT_CLASSES; i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
if(stricmp(genericpage->anim_sound_name[i][j], "INVALID NAME") && genericpage->anim_sound_name[i][j][0]!=0)
{
int anim_sound_handle = mng_GetGuaranteedSoundPage (genericpage->anim_sound_name[i][j]);
if (anim_sound_handle < 0)
{
mprintf ((0,"Couldn't load anim sound file '%s' in AssignPowPage %s...\n",genericpage->anim_sound_name[i][j],genericpage->objinfo_struct.name));
objinfopointer->anim[i].elem[j].anim_sound_index = SOUND_NONE_INDEX;
}
else
objinfopointer->anim[i].elem[j].anim_sound_index = anim_sound_handle;
}
else
objinfopointer->anim[i].elem[j].anim_sound_index = SOUND_NONE_INDEX;
}
}
}
// objinfopointer->size=(ComputeDefaultSize(objinfopointer->render_handle, &objinfopointer->size_offset, 0, 0));
return 1;
}
// Copies values from a generic into a generic_page
void mng_AssignObjInfoToGenericPage(int n,mngs_generic_page *genericpage)
{
object_info *objinfopointer=&Object_info[n];
int i,j;
// Assign the values
memcpy (&genericpage->objinfo_struct,objinfopointer,sizeof(*objinfopointer));
strcpy (genericpage->objinfo_struct.name,objinfopointer->name);
if(objinfopointer->anim)
memcpy(&genericpage->anim,objinfopointer->anim,sizeof(genericpage->anim));
if(objinfopointer->static_wb)
memcpy(&genericpage->static_wb,objinfopointer->static_wb,sizeof(genericpage->static_wb));
if(objinfopointer->ai_info)
memcpy(&genericpage->ai_info,objinfopointer->ai_info,sizeof(genericpage->ai_info));
if (objinfopointer->description!=NULL)
{
int len=strlen (objinfopointer->description);
genericpage->objinfo_struct.description=(char *)mem_malloc(len+1);
ASSERT (genericpage->objinfo_struct.description);
strcpy (genericpage->objinfo_struct.description,objinfopointer->description);
}else
genericpage->objinfo_struct.description = NULL;
strcpy(genericpage->objinfo_struct.icon_name,objinfopointer->icon_name);
if (objinfopointer->render_handle!=-1)
strcpy (genericpage->image_name,Poly_models[objinfopointer->render_handle].name);
else
strcpy (genericpage->image_name,"");
if (objinfopointer->med_render_handle!=-1)
strcpy (genericpage->med_image_name,Poly_models[objinfopointer->med_render_handle].name);
else
strcpy (genericpage->med_image_name,"");
if (objinfopointer->lo_render_handle!=-1)
strcpy (genericpage->lo_image_name,Poly_models[objinfopointer->lo_render_handle].name);
else
strcpy (genericpage->lo_image_name,"");
for (i=0;i<MAX_OBJ_SOUNDS;i++)
{
if (objinfopointer->sounds[i]!=SOUND_NONE_INDEX)
strcpy (genericpage->sound_name[i],Sounds[objinfopointer->sounds[i]].name);
else
strcpy (genericpage->sound_name[i],"");
}
for (i=0; i<MAX_DSPEW_TYPES;i++)
{
if((objinfopointer->dspew[i] != -1) && Object_info[objinfopointer->dspew[i]].type != OBJ_NONE)
strcpy(genericpage->dspew_name[i], Object_info[objinfopointer->dspew[i]].name);
else
strcpy(genericpage->dspew_name[i], "\0");
}
for (i=0;i<MAX_AI_SOUNDS;i++)
{
if (objinfopointer->ai_info && objinfopointer->ai_info->sound[i] != SOUND_NONE_INDEX)
strcpy (genericpage->ai_sound_name[i],Sounds[objinfopointer->ai_info->sound[i]].name);
else
strcpy (genericpage->ai_sound_name[i],"");
}
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_FIRING_MASKS; j++)
{
if (objinfopointer->static_wb && objinfopointer->static_wb[i].fm_fire_sound_index[j] >= 0)
strcpy (genericpage->fire_sound_name[i][j], Sounds[objinfopointer->static_wb[i].fm_fire_sound_index[j]].name);
else
strcpy (genericpage->fire_sound_name[i][j],"");
}
}
for(i = 0; i < NUM_MOVEMENT_CLASSES; i++)
{
for(j = 0; j < NUM_ANIMS_PER_CLASS; j++)
{
if (objinfopointer->anim && objinfopointer->anim[i].elem[j].anim_sound_index >= 0)
strcpy (genericpage->anim_sound_name[i][j], Sounds[objinfopointer->anim[i].elem[j].anim_sound_index].name);
else
strcpy (genericpage->anim_sound_name[i][j],"");
}
}
for(i = 0; i < MAX_WBS_PER_OBJ; i++)
{
for(j = 0; j < MAX_WB_GUNPOINTS; j++)
{
if (objinfopointer->static_wb && objinfopointer->static_wb[i].gp_weapon_index[j] >= 0)
strcpy (genericpage->weapon_name[i][j], Weapons[objinfopointer->static_wb[i].gp_weapon_index[j]].name);
else
strcpy (genericpage->weapon_name[i][j],"Laser");
}
}
}
// Loads a generic found in the net table file. It then allocs a generic and
// then calls SetAndLoadgeneric to actually load in any images/models associated
// with it
void mng_LoadNetGenericPage(CFILE *infile,bool overlay)
{
mngs_generic_page genericpage;
memset(&genericpage, 0, sizeof(mngs_generic_page));
if (mng_ReadNewGenericPage (infile,&genericpage))
{
int n = FindObjectIDName (genericpage.objinfo_struct.name);
if (n!=-1)
{
if(overlay)
{
mprintf((0,"OVERLAYING GENERIC %s\n",genericpage.objinfo_struct.name));
mng_FreePagetypePrimitives (PAGETYPE_GENERIC,genericpage.objinfo_struct.name,0);
mng_AssignGenericPageToObjInfo(&genericpage,n);
}
return; // A weapon has already loaded this generic
}
int ret=mng_SetAndLoadGeneric (&genericpage,infile);
ASSERT (ret>=0);
}
else
mprintf ((0,"Could not load genericpage named %s!\n",genericpage.objinfo_struct.name));
}
// Reads a generic page from a local table file. It then allocs a generic and
// loads any images/models associated with that generic
void mng_LoadLocalGenericPage(CFILE *infile)
{
mngs_generic_page genericpage;
int ok=0;
memset(&genericpage, 0, sizeof(mngs_generic_page));
if (mng_ReadNewGenericPage (infile,&genericpage))
{
// Check to see if this is a local copy that is supposed
// to go over a network copy (supersede the net copy)
int i=FindObjectIDName (genericpage.objinfo_struct.name);
if (i!=-1)
{
// Make sure we really have this page checked out
mngs_Pagelock pl;
strcpy (pl.name,genericpage.objinfo_struct.name);
pl.pagetype=PAGETYPE_GENERIC;
/*if (Network_up && Stand_alone==0)
{
int locked=mng_CheckIfPageOwned(&pl,TableUser);
if (locked!=1)
Int3(); // Your local vs net copies of the lock file do not match
}*/
ok=1;
bool need_to_load_page = true;
if (Loading_addon_table!=-1)
{
AddOnTablefile *addon;
int tidx;
// see if we really need to load this page
//check to see if we already have loaded this page (because it was
//a dependancy of another)
addon = &AddOnDataTables[Loading_addon_table];
for(tidx=0;tidx<addon->Num_addon_tracklocks;tidx++)
{
if(addon->Addon_tracklocks[tidx].pagetype==PAGETYPE_GENERIC &&
!stricmp(addon->Addon_tracklocks[tidx].name,genericpage.objinfo_struct.name) )
{
// found it!!
mprintf((0,"GenericPage: %s previously loaded\n",genericpage.objinfo_struct.name));
need_to_load_page = false;
break;
}
}
}
if(need_to_load_page)
{
mng_FreePagetypePrimitives (PAGETYPE_GENERIC,genericpage.objinfo_struct.name,0);
mng_AssignGenericPageToObjInfo (&genericpage,i);
// For addon data
if (Loading_addon_table!=-1)
{
// this is an overlay of some sort..see which we are overlaying
int overlay = 1;
int addidx,tidx;
bool found = false;
for(addidx = Num_addon_tables-1; addidx>=0; addidx--)
{
if(addidx==Loading_addon_table)
continue;
AddOnTablefile *addon = &AddOnDataTables[addidx];
// look for the page in this table file
for(tidx=0;tidx<addon->Num_addon_tracklocks;tidx++)
{
if(addon->Addon_tracklocks[tidx].pagetype==PAGETYPE_GENERIC &&
!stricmp(addon->Addon_tracklocks[tidx].name,genericpage.objinfo_struct.name) )
{
// found it!!
found = true;
overlay = addidx+2;
break;
}
}
if(found)
break;
}
mng_PushAddonPage (PAGETYPE_GENERIC,genericpage.objinfo_struct.name,overlay);
}
}
}
else
{
// This is a local generic that has never been checked in
if ((i=mng_SetAndLoadGeneric (&genericpage))<0)
ok=0;
else ok=1;
// For addon data
if (ok && Loading_addon_table!=-1)
mng_PushAddonPage (PAGETYPE_GENERIC,genericpage.objinfo_struct.name,0);
}
ASSERT (ok==1);
if (Loading_addon_table==-1)
mng_AllocTrackLock (genericpage.objinfo_struct.name,PAGETYPE_GENERIC);
}
else
mprintf ((0,"Could not load genericpage named %s!\n",genericpage.objinfo_struct.name));
}
// First searches through the object index to see if the object is already
// loaded. If not, searches in the table file and loads it.
// Returns index of object found, -1 if not
int mng_GetGuaranteedGenericPage (char *name,CFILE *infile)
{
int i;
mngs_generic_page page;
// See if its in memory
i = FindObjectIDName(name);
if (i!=-1)
return i;
// Not in memory. Load it from the table file. Start searching from the
// current spot in the open table file
int ret = mng_FindSpecificGenericPage(name,&page,infile?infile->position:0);
if (!ret)
return -1;
// We've found it in the table file, now load it.
ret = mng_SetAndLoadGeneric(&page);
ASSERT (ret>=0);
if(Loading_addon_table!=-1)
{
// we're loading addon table pages, this will not overlay anything
mng_PushAddonPage (PAGETYPE_GENERIC,page.objinfo_struct.name,0);
}
return ret;
}