You are not logged in.    Login    New User    Forum Home    Search

Location:
JBPLAY  \  Meteor 2  \  Help and Guidance  \  Help with scripting sounds

Back to Threads

Viewing Thread: Help with scripting sounds

 

Canuck

Joined: 31 August 2007
Posts: 419
18 August 2008 03:59 (UK time)

Okay.... does anyone see any reason why this sound would not play when the script is called?


void Boost()
{
if (SC_GetItemCount("Speed Boost")==0)
{
SC_GameMessage("You have no speed boosts to use!");
}
else
{
SC_SetObjectMaxSpeed(SC_GetPlayerObjectId(),14);
SC_BindObjectToWaypoint(3,155);
SC_PlaySound("Race\\Boost");
SC_GiveItem("Speed Boost",-1);
}
}


All the other functions in this script work fine, but the sound will not play. The sound itself is in the mod's sound folder in a subfolder entitled 'Race'. It is a WAV file. I am totally perplexed.

You need to login to create posts in this thread.

40oz
 Official Sponsor

Joined: 03 January 2004
Posts: 1799
18 August 2008 04:01 (UK time)

Did you try moving the sound around in different folders? Test to see if it works when the sound is in the base sound folder to see if it's not a problem with M2's code but a problem with the script detecting the sound. I think the console may also tell you if the sound does not exist.
*Papercut
Pro-Murder.
Legalize Crime.


You need to login to create posts in this thread.

Canuck

Joined: 31 August 2007
Posts: 419
18 August 2008 04:15 (UK time)

Oh, hang on, that was a login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
18 August 2008 16:00 (UK time)

The fact that you always have to reload the game data after modding sometimes really pisses me off =P

Can't the game just ADD the new sound to the data instead of always re-initialising the whole game?!


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


You need to login to create posts in this thread.

40oz
 Official Sponsor

Joined: 03 January 2004
Posts: 1799
18 August 2008 16:08 (UK time)

Yeah, it's hell if you have a slow computer, I used to have a computer that it would take almost a good 30 seconds to reload the game data each time.

It's really a pain if you really want to get things done. For Example:

Step 1 - Make the sprites in the sprite builder. Reload Data

Step 2 - Make the projectile in the projectile editor. Reload Data

Step 3 - Make the Weapon that fires the projectile in the weapon editor. Reload Data

Step 4 - Make the object that holds the weapon in the object editor. Oops, I forgot to make a wasted sprite. Reload data

Step 5 - Make the sprite in sprite builder. Reload Data

Step 6 - Modify the object. Reload data

Step 7 - Load texture images so you can test the object in the map editor.

Okay! Now after reloading the game data six times, I finally have finished making 1 object!X(
*Papercut
Pro-Murder.
Legalize Crime.


Edited: 18 August 2008 16:10


You need to login to create posts in this thread.

Canuck

Joined: 31 August 2007
Posts: 419
18 August 2008 16:53 (UK time)

Hmmm.... maybe if there was a button for 'Check for new/modified data' that would scan through the game files and only reload ones that were new or different. That might speed it up.

You need to login to create posts in this thread.

Knasp

Joined: 18 June 2004
Posts: 158
18 August 2008 17:12 (UK time)

Yeah, either that or the game automatically reloads game data when you exit an editor after saving something.

I'd prefer if it just would add the data...

Edited: 18 August 2008 17:13


You need to login to create posts in this thread.

Canuck

Joined: 31 August 2007
Posts: 419
18 August 2008 20:02 (UK time)

It's funny, too, because you don't have to reload new items or new/modified script files (Can you imagine what a pain it would be if you did?). Maybe the same thing could be done for the rest of the data.

You need to login to create posts in this thread.

arezey

Joined: 16 June 2005
Posts: 1599
18 August 2008 20:09 (UK time)

Canuck wrote:
Maybe the same thing could be done for the rest of the data.


I doubt it, as I believe the data it loads during those reloads is used to render the sprites/objects/... into the editors. I think the items in fact are loaded as well; however, as they're just one file it takes like a flash to load it, so it can be loaded, say whenever the map editor is booted up. Script files are loaded when the map is being run.

Of course, as I don't have the Meteor source code I can't tell for sure but that's how I've theorized it. I wonder what James would have to say about that ;)

You need to login to create posts in this thread.

James Bunting
Joined: 17 September 2003
Posts: 1308
19 August 2008 01:29 (UK time)

All totally correct yes.

If you alt-tab out and add a file how does Meteor know without making it look through all of the folders?

Then of course an existing file may have changed so it has to look in each file too.

So it just reloads it all. :p

And yes it is all related and needs to be loaded in order so when you exit an editor it "refreshes" the data.

Basically everying it loaded into memory and linked up to make the game faster. If sounds were not preloaded and indexed (by number) then it would be really slow to play.

For example...

1. Sounds are loaded and numbered
2. Other stuff that uses sounds are loaded
3. Sound filenames in the "other stuff" are converted to numbers to fast access

Of course the reality is that the game is one big relational database in memory. Everthing has to be loaded in order and indexed.

Everying is numbered and connected, the all "filename links" between all elements is only used when saving and loading files.

Check out this loader code snippet from Meteor 2 (I am always happy to release my file specs anyway)


// loads all sprites and objects etc from the base and mod folders
void FIL_LoadGameData()
{
int i;
char filename[FILENAME_LEN];

FIL_UnloadGameData();

// load wave files
AUD_LoadWaveFiles();

FIL_CreateDefaultThings();

// init items
MSG_BigMessage( BUTTON_RUN, "Initialising items");
ITEMS_Init();

// read game defs file (BEFORE DATA LOADER)
strcpy( filename, FILE_GAME_DEFS);
FIL_GetFirstFilename( filename);
MSG_Message("FIL_LoadGameData: Using game defs file %s", filename);
FIL_ReadGameInfoFile(filename,1);

//*************************************************
// *** load game data ***

// Ensure that each type of data (images, sprites etc) is entirely loaded
// before loading the next type. This is important for modded data.

// images
if( DAT_UsingMod)
FIL_LoadImages(1);
FIL_LoadImages(0);

// textures
if( DAT_UsingMod)
FIL_LoadTextures(1);
FIL_LoadTextures(0);

// sprites
if( DAT_UsingMod)
FIL_LoadSprites(1);
FIL_LoadSprites(0);

// projectiles
if( DAT_UsingMod)
FIL_LoadProjectiles(1);
FIL_LoadProjectiles(0);

// weapons
if( DAT_UsingMod)
FIL_LoadWeapons(1);
FIL_LoadWeapons(0);

// objects
if( DAT_UsingMod)
FIL_LoadObjects(1);
FIL_LoadObjects(0);

// *** end loading game data
//*************************************************

// read game defs file (AGAIN AFTER DATA LOADER)
FIL_ReadGameInfoFile(filename,0);

// set power up sprite numbers
for( i=0; i<DAT_ItemsData.PowerUpsCount; ++i)
{
DAT_ItemsData.PowerUps[i].SpriteNumber = SPR_GetSpriteNumberForName( DAT_ItemsData.PowerUps[i].SpriteName);
}

// set driver object numbers for object types
for( i=0; i<DAT_LoadedObjectTypes.count; ++i)
{
DAT_LoadedObjectTypes.objects[i].a_DefaultDriverObjectNumber = OBJED_ResolveDriverObjectName( DAT_LoadedObjectTypes.objects[i].DefaultDriverObjectName);
}

// set special numbers
DAT_GameDefs.FireSpriteNumber = SPR_GetSpriteNumberForName( "effects\\fire.spr");
DAT_GameDefs.DefaultShrapnelSpriteNumber = SPR_GetSpriteNumberForName("effects\\shrapnel.spr");
DAT_GameDefs.HitPointItemNumber = ITEMS_GetItemNumber( "Hit Point");
DAT_GameDefs.VehicleHitPointItemNumber = ITEMS_GetItemNumber( "Vehicle Hit Point");
DAT_GameDefs.GodModeItemNumber = ITEMS_GetItemNumber( "God Mode");
DAT_GameDefs.FlashlightItemNumber = ITEMS_GetItemNumber( "Flashlight");
DAT_GameDefs.HudAmmoSpriteNumber = SPR_GetSpriteNumberForName( "hud\\ammo.spr");
DAT_GameDefs.HudKillsSpriteNumber = SPR_GetSpriteNumberForName( "hud\\frags.spr");
DAT_GameDefs.PowerUpTimerSpriteNumber = SPR_GetSpriteNumberForName( "objects\\timer.spr");
DAT_GameDefs.SmokeSpriteNumber = SPR_GetSpriteNumberForName( "effects\\smoke.spr");
DAT_GameDefs.LaserDotSpriteNumber = SPR_GetSpriteNumberForName( "effects\\LaserDot.spr");
DAT_GameDefs.BulletLineImageNumber = GFX_GetImageNumForName( "effects\\BulletLine01_01.pcx");
DAT_GameDefs.LaserLineImageNumber = GFX_GetImageNumForName( "effects\\LaserLine01_01.pcx");
DAT_GameDefs.LaserLine2ImageNumber = GFX_GetImageNumForName( "effects\\LaserLine02_01.pcx");
DAT_GameDefs.HealthIconNumber_Human = SPR_GetSpriteNumberForName( "hud\\HealthIcon_Human.spr");
DAT_GameDefs.HealthIconNumber_Tank = SPR_GetSpriteNumberForName( "hud\\HealthIcon_Tank.spr");

// generate side images
GFX_GenerateSideImages();

// check for data errors (do this before loading the menu background)
DE_ScanForDataErrors();

// load menu background bitmap
MENU_LoadMenuBackdrop();

// reset weapon type id numbers
ID_ResetAllWeaponTypeIds();

GameDataLoaded = 1;
}

void FIL_LoadImages( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;

MSG_BigMessage( BUTTON_RUN, "Loading images");

strcpy( FullPath, PATH_IMAGES);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedImages.count >= MAX_LOADED_IMAGES)
{
MSG_Message("Can not load more than %d images!", MAX_LOADED_IMAGES);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
// MSG_Message("Loading image from %s", list.items[i].filename);
if( !FIL_IsImageAlreadyLoaded( list.items[i].filename))
{

DAT_LoadedImages.ImageData = realloc( DAT_LoadedImages.ImageData, sizeof(TLOADED_IMAGE) * (DAT_LoadedImages.count+1) );
if( DAT_LoadedImages.ImageData == NULL)
APP_FatalError("Unable to reallocate images buffer");

strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);

if(( DAT_LoadedImages.ImageData[ DAT_LoadedImages.count].image = IO_LoadBitmap( filename)) != NULL)
{
MEM_StrAllocCopy( &DAT_LoadedImages.ImageData[ DAT_LoadedImages.count].filename, list.items[i].filename);
DAT_LoadedImages.ImageData[ DAT_LoadedImages.count ].HasSideImages = 0;
DAT_LoadedImages.count++;
loaded ++;
// MSG_Message("Loaded image from %s, number = %d", filename, DAT_LoadedImages.count-1);
}
else
MSG_Message("Error Loading image from %s", filename);
}
}
}
}

JDIR_DestroyDirectoryList( &list);

MSG_Message("Loaded %d images(s) from \"%s\"", loaded, FullPath);
}

void FIL_LoadTextures( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;
BITMAP *TempMinimapBitmap;

MSG_BigMessage( BUTTON_RUN, "Loading textures");

TempMinimapBitmap = MISC_NewBitmap( 1, 1);
sprintf( FullPath, "%s", PATH_TEXTURES);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedTextures.count >= MAX_LOADED_TEXTURES)
{
MSG_Message("Can not load more than %d textures!", MAX_LOADED_TEXTURES);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
strcpy( filename, JDIR_GetFilenameForNumber( &list, i) );
if( filename != NULL)
{
if( !MISC_DoesStringExistInArray( list.items[i].filename, DAT_LoadedTextures.names, DAT_LoadedTextures.count))
{
// store full path filename
strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);
MEM_StrAllocCopy( &DAT_LoadedTextures.TextureData[ DAT_LoadedTextures.count].FullPathFilename, filename);

// store filename (no path)
MEM_StrAllocCopy( &DAT_LoadedTextures.names[ DAT_LoadedTextures.count], list.items[i].filename);

// set unloaded texture image
TEX_SetDefaultTextureImage( DAT_LoadedTextures.count);

DAT_LoadedTextures.TextureData[ DAT_LoadedTextures.count].loaded = 0;
DAT_LoadedTextures.count++;
loaded ++;
}
}
}
}
}

JDIR_DestroyDirectoryList( &list);
MSG_Message("Loaded %d textures(s) from \"%s\"", loaded, FullPath);

}

void FIL_LoadSprites( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;
MSG_BigMessage( BUTTON_RUN, "Loading sprites");

strcpy( FullPath, PATH_SPRITES);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedSprites.count>=MAX_TSPRITES)
{
MSG_Message("Can not load more than %d sprites!", MAX_TSPRITES);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
if( !MISC_DoesStringExistInArray( list.items[i].filename, DAT_LoadedSprites.names, DAT_LoadedSprites.count))
{
#ifdef DEBUG_MODE
MSG_Message("Loading sprite from %s", list.items[i].filename);
#endif

strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);

if( FIL_ReadSpriteFile( filename, &DAT_LoadedSprites.sprites[ DAT_LoadedSprites.count], 0 ))
{
MEM_StrAllocCopy( &DAT_LoadedSprites.names[ DAT_LoadedSprites.count], list.items[i].filename);
DAT_LoadedSprites.count++;
loaded ++;
}

#ifdef DEBUG_MODE
MSG_Message("Done loading sprite");
#endif
}
}
}
}

JDIR_DestroyDirectoryList( &list);
MSG_Message("Loaded %d sprite(s) from \"%s\"", loaded, FullPath);
}

void FIL_LoadProjectiles( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;

MSG_BigMessage( BUTTON_RUN, "Loading projectiles");

strcpy( FullPath, PATH_PROJECTILES);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedProjectiles.count>=MAX_PTILE_TYPES)
{
MSG_Message("Can not load more than %d projectiles!", MAX_PTILE_TYPES);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
if( !MISC_DoesStringExistInArray( list.items[i].filename, DAT_LoadedProjectiles.names, DAT_LoadedProjectiles.count))
{
strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);

if( FIL_ReadProjectileFile( filename, &DAT_LoadedProjectiles.projectiles[ DAT_LoadedProjectiles.count], 0))
{
MEM_StrAllocCopy( &DAT_LoadedProjectiles.names[ DAT_LoadedProjectiles.count], list.items[i].filename);
DAT_LoadedProjectiles.count++;
loaded ++;
}
}
}
}
}

JDIR_DestroyDirectoryList( &list);
MSG_Message("Loaded %d projectile(s) from \"%s\"", loaded, FullPath);
}

void FIL_LoadWeapons( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;
MSG_BigMessage( BUTTON_RUN, "Loading weapons");

strcpy( FullPath, PATH_WEAPONS);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedWeapons.count >= MAX_WEAPONS)
{
MSG_Message("Can not load more than %d weapons!", MAX_WEAPONS);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
if( !MISC_DoesStringExistInArray( list.items[i].filename, DAT_LoadedWeapons.names, DAT_LoadedWeapons.count))
{
strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);

if( FIL_ReadWeaponFile( filename, &DAT_LoadedWeapons.weapons[ DAT_LoadedWeapons.count], 0))
{
MEM_StrAllocCopy( &DAT_LoadedWeapons.names[ DAT_LoadedWeapons.count], list.items[i].filename);
DAT_LoadedWeapons.count++;
loaded ++;
}
}
}
}
}

JDIR_DestroyDirectoryList( &list);
MSG_Message("Loaded %d weapons(s) from \"%s\"", loaded, FullPath);
}

void FIL_LoadObjects( char inUseModFolder)
{
char FullPath[FILENAME_LEN], filename[FILENAME_LEN];
TDIRLIST list;
int loaded, i;
MSG_BigMessage( BUTTON_RUN, "Loading objects");

strcpy( FullPath, PATH_OBJECTS);
FIL_AddBasePathPrefix( FullPath, inUseModFolder);
JDIR_CreateDirectoryList( &list, FullPath, "*.*", DIRMODE_FILES, 1);
loaded = 0;

for( i=0; i<list.count; ++i)
{
if( DAT_LoadedWeapons.count >= MAX_OBJECT_TYPES)
{
MSG_Message("Can not load more than %d weapons!", MAX_WEAPONS);
i = list.count; // break loop
}
else
{
if( list.items[i].filename != NULL)
{
if( !MISC_DoesStringExistInArray( list.items[i].filename, DAT_LoadedObjectTypes.names, DAT_LoadedObjectTypes.count))
{
strcpy( filename, list.items[i].filename);
JDIR_AddPathToFront( filename, FullPath);

if( FIL_ReadObjectFile( filename, &DAT_LoadedObjectTypes.objects[ DAT_LoadedObjectTypes.count], 0))
{
MEM_StrAllocCopy( &DAT_LoadedObjectTypes.names[ DAT_LoadedObjectTypes.count], list.items[i].filename);
DAT_LoadedObjectTypes.count++;
loaded ++;
}
}
}
}
}

JDIR_DestroyDirectoryList( &list);
MSG_Message("Loaded %d objects(s) from \"%s\"", loaded, FullPath);
}

int FIL_ReadSpriteFile( char *filename, TSPRITE *s, int inDestroyCurrent)
{
int i;
char TempBuf[2];
TSTANDARD_FILE_HEADER hdr;
FILE *f;

if( !FIL_OpenFile( &f, filename, "rb"))
return 0;

#ifdef DEBUG_MODE
MSG_Message("FIL_ReadSpriteFile: Reading sprite from %s", filename);
#endif

// check for old ini sprite format
fread( TempBuf, 1, 1, f);
fseek( f, 0, 0);
if( TempBuf[0] != SPRITE_ID[0])
{
// ** old ini sprite file format **

// reopen as text/ini
fclose(f);
if( !FIL_OpenFile( &f, filename, "r"))
return 0;

if( !IOL_ReadOldSpriteFile( f, s, inDestroyCurrent, filename))
return 0;
}
else
{
// ** newer binary format **

// read and check header
fread( &hdr, sizeof(hdr), 1, f);
if( !JG_CheckFileHeader( &hdr, SPRITE_ID, SPRITE_VERSION, filename, 0, 0))
{
MSG_Message("%s: Bad file version", filename);
fclose(f);
return 0;
}

// destroy current?
if( inDestroyCurrent)
SB_DestroySprite( s);

// read basic info
JG_ReadString( f, s->name);
JG_ReadByte( f, &s->NumFrames);
JG_ReadByte( f, &s->NumSubs);
JG_ReadByte( f, &s->NumLights);
JG_ReadString( f, s->LoopSoundName);
s->a_LoopSoundNumber = AUD_GetSoundNumberForName( s->LoopSoundName);

// check frame count is not too high
if( s->NumFrames > MAX_SPRITE_FRAMES)
{
fclose(f);
APP_FatalError("FIL_ReadSpriteFile: %s, frame count exceeds %d", filename, MAX_SPRITE_FRAMES);
}

// set currrent frame
s->a_CurrentFrame = 0;

// read frames
for( i=0; i< s->NumFrames; ++i)
{
JG_ReadInt( f, &s->frames[i].DisplayTime);
JG_ReadString( f, s->frames[i].ImageName);
s->frames[i].a_ImageNumber = GFX_GetImageNumForName( s->frames[i].ImageName);
JG_ReadString( f, s->frames[i].SoundName);

// calc
s->frames[i].a_SoundNumber = AUD_GetSoundNumberForName(s->frames[i].SoundName);
}

// read subs
for( i=0; i<s->NumSubs; ++i)
{
JG_ReadString( f, s->subs[i].name);
JG_ReadInt( f, &s->subs[i].xp);
JG_ReadInt( f, &s->subs[i].yp);
JG_ReadInt( f, &s->subs[i].rotate);
JG_ReadString( f, s->subs[i].ImageName);
s->subs[i].a_ImageNumber = GFX_GetImageNumForName( s->subs[i].ImageName);
}

// read lights
for( i=0; i<s->NumLights; ++i)
{
LT_ReadLightObjectFromBinaryFile( f, &s->lights[i].light);
JG_ReadInt( f, &s->lights[i].x);
JG_ReadInt( f, &s->lights[i].y);

// allocate light object
LT_InitLightObject( &s->lights[i].light, 0);
}

fclose( f);
}

// create RID for this sprite (based on 1st frame)
JG_CreateRotatedImageData( &s->rid, DAT_LoadedImages.ImageData[ s->frames[ 0].a_ImageNumber].image, 1);

// do calc stuff for subs
for( i=0; i<s->NumSubs; ++i)
{
// MSG_Message("Creating RID for sub %d", i);
JG_CreateRotatedImageData( &s->subs[i].rid, M_SPRITE_SUB_BITMAP(s, i), 1);

// MSG_Message("Creating rotated offsets for sub %d", i);
s->subs[i].RotatedOffsetsAllocated = 0;
SUB_UpdateSubRotatedOffsets( s, i);

// MSG_Message("Done with sub %d", i);
}

// do calc stuff for lights
for( i=0; i<s->NumLights; ++i)
{
// create and update rotated offsets
s->lights[i].RotatedOffsetsAllocated = 0;
SB_UpdateRotatedLightOffsets( s, i);
}


// clear sprite's default animation data
SPR_ResetAnimationData( &s->DefaultAnimationData);

#ifdef DEBUG_MODE
MSG_Message("FIL_ReadSpriteFile: Loaded sprite from %s", filename);
#endif

return 1;
}

int FIL_WriteSpriteFile( char *filename, TSPRITE *s)
{
int i;
FILE *f;
TSTANDARD_FILE_HEADER hdr;

if( !FIL_OpenFile( &f, filename, "wb"))
return 0;

JG_SetStandardFileHeaderDetails( &hdr, SPRITE_ID, SPRITE_VERSION);
fwrite( &hdr, sizeof(hdr), 1, f);

JG_WriteString( f, s->name);
JG_WriteByte( f, s->NumFrames);
JG_WriteByte( f, s->NumSubs);
JG_WriteByte( f, s->NumLights);
JG_WriteString( f, s->LoopSoundName);

// write frames
for( i=0; i< s->NumFrames; ++i)
{
JG_WriteInt( f, s->frames[i].DisplayTime);
JG_WriteString( f, s->frames[i].ImageName);
JG_WriteString( f, s->frames[i].SoundName);
}

// write subs
for( i=0; i<s->NumSubs; ++i)
{
JG_WriteString( f, s->subs[i].name);
JG_WriteInt( f, s->subs[i].xp);
JG_WriteInt( f, s->subs[i].yp);
JG_WriteInt( f, s->subs[i].rotate);
JG_WriteString( f, s->subs[i].ImageName);
}

// write lights
for( i=0; i<s->NumLights; ++i)
{
LT_WriteLightObjectToBinaryFile( f, &s->lights[i].light);
JG_WriteInt( f, s->lights[i].x);
JG_WriteInt( f, s->lights[i].y);
}

fclose( f);

return 1;
}

int FIL_ReadObjectFile( char *filename, TOBJECT_TYPE *r, int inDestroyCurrent)
{
FILE *f;
int i, a;
double bear, dist, TraceX, TraceY;
double cx, cy, MountCentreX, MountCentreY;
unsigned char TraceBearing;
char section[ 32];

if( !FIL_OpenFile( &f, filename, "r"))
return 0;

if( !FIL_CheckINIFileHeader( f, OBJECT_ID, OBJECT_VERSION, filename))
{
fclose( f);
return 0;
}

if( inDestroyCurrent)
OBJED_DestroyObject( r);

strcpy( section, "info");
strcpy( r->desc, JINI_ReadString( f, section, "desc", NONE));

r->ObjectClass = JINI_ReadInt( f, section, "ObjectClass", OC_INFANTRY);
r->hp = JINI_ReadInt( f, section, "hp", 20);
r->ArmourResist = JINI_ReadInt( f, section, "ArmourResist", 0);
r->sight = JINI_ReadInt( f, section, "sight", 20);
r->speed = JINI_ReadInt( f, section, "speed.AmountToMove", 4);
r->MaxHeight = JINI_ReadInt( f, section, "MaxHeight", 15);
r->vehicle = JINI_ReadByte( f, section, "vehicle", 0);
r->WeaponsRotate = JINI_ReadByte( f, section, "WeaponsRotate", 0);
r->AllowShadow = JINI_ReadByte( f, section, "AllowShadow", 1);
r->WhiteColourSwapOnly = JINI_ReadByte( f, section, "WhiteColourSwapOnly", 1);
r->explodes = JINI_ReadByte( f, section, "explodes", 0);
r->ExplodeRadius = JINI_ReadInt( f, section, "ExplodeRadius", 40);
r->ExplodeDamage = JINI_ReadInt( f, section, "ExplodeDamage", 60);

r->DefaultAiType = JINI_ReadInt( f, section, "DefaultAiType", AI_ROAMING);

r->organic = JINI_ReadByte( f, section, "organic", 0);
r->RunDown = JINI_ReadByte( f, section, "RunDown", 1);
r->IsMechanic = JINI_ReadByte( f, section, "IsMechanic", 0);
r->IsMedic = JINI_ReadByte( f, section, "IsMedic", 0);


strcpy( r->StillSpriteName, JINI_ReadString( f, section, "StillSpriteName", ""));
strcpy( r->MovingSpriteName, JINI_ReadString( f, section, "MovingSpriteName", ""));
strcpy( r->WastedSpriteName, JINI_ReadString( f, section, "WastedSpriteName", ""));

r->HasFixedLaser = JINI_ReadByte( f, section, "HasFixedLaser", 0);
r->FixedLaserColour.r = JINI_ReadByte( f, section, "FixedLaserColour.r", 255);
r->FixedLaserColour.g = JINI_ReadByte( f, section, "FixedLaserColour.g", 0);
r->FixedLaserColour.b = JINI_ReadByte( f, section, "FixedLaserColour.b", 0);

strcpy( r->RandomSoundName, JINI_ReadString( f, section, "RandomSoundName", NOSOUND));
strcpy( r->DestroyedSoundName, JINI_ReadString( f, section, "DestroyedSoundName", NOSOUND));
strcpy( r->HooterSoundName, JINI_ReadString( f, section, "HooterSoundName", SOUND_VEHICLE_HOOTER));
strcpy( r->HurtSoundName, JINI_ReadString( f, section, "HurtSoundName", NOSOUND));
strcpy( r->EnterSoundName, JINI_ReadString( f, section, "EnterSoundName", SOUND_VEHICLE_IN));
strcpy( r->ExitSoundName, JINI_ReadString( f, section, "ExitSoundName", SOUND_VEHICLE_OUT));

strcpy( r->DefaultDriverObjectName, JINI_ReadString( f, section, "DefaultDriverObjectName", DAT_GameDefs.DefaultDriverObject) );
r->DefaultCrewCount = JINI_ReadInt( f, section, "DefaultCrewCount", 1);

strcpy( r->DropPowerUpName, JINI_ReadString( f, section, "DropPowerUpName", ""));
strcpy( r->DropPowerUpName2, JINI_ReadString( f, section, "DropPowerUpName2", ""));
strcpy( r->DropPowerUpNameMP, JINI_ReadString( f, section, "DropPowerUpNameMP", ""));

r->NumMounts = JINI_ReadInt( f, section, "NumMounts", 0);


// * do offsets before setting weapon mounts! *

// calc data
r->a_StillSpriteNumber = SPR_GetSpriteNumberForName( r->StillSpriteName);
r->a_MovingSpriteNumber = SPR_GetSpriteNumberForName( r->MovingSpriteName);

// DO NOT STORE DefaultDriverObjectNumber HERE AS ALL OBJECTS MAY NOT BE LOADED

if( strlen( r->WastedSpriteName) < 1)
r->a_WastedSpriteNumber = -1;
else
{
r->a_WastedSpriteNumber = SPR_GetSpriteNumberForName( r->WastedSpriteName);
}

// read weapon mounts
r->a_HasLaser = 0;
for( i=0; i<r->NumMounts; ++i)
{
sprintf( section, "WeaponMount%d", i);
r->WeaponMounts[i].x = JINI_ReadInt( f, section, "x", 0);
r->WeaponMounts[i].y = JINI_ReadInt( f, section, "y", 0);
strcpy( r->WeaponMounts[i].WeaponName, JINI_ReadString( f, section, "WeaponName", ""));

// set weapon number
r->WeaponMounts[i].a_WeaponNumber = WED_GetWeaponNumberForName( r->WeaponMounts[i].WeaponName);

if( !r->a_HasLaser)
r->a_HasLaser = DAT_LoadedWeapons.weapons[ r->WeaponMounts[i].a_WeaponNumber].HasLaser;

// create/update weapon draw offsets
OBJED_UpdateWeaponMountOffsets( r, i);


// *************************************************************
// ** calculate firing point offsets **


// * calculate mount centre offsets *
// this is the arc that the centre of the mount travels along when the object rotates

// get the coords of the centre of the object's canvas
cx = M_OBJECT_PTR_STILL_IMAGE( r)->w /2;
cy = M_OBJECT_PTR_STILL_IMAGE( r)->h /2;

// get the mount centre pos on the object (add offsets and half width/height)
MountCentreX = r->WeaponMounts[i].x + ( M_SPRITEN_W( DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].SpriteNumber, 0) / 2);
MountCentreY = r->WeaponMounts[i].y + ( M_SPRITEN_H( DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].SpriteNumber, 0) / 2);

// get the bearing from the canvas centre to the mount centre
bear = JG_GetBearing( cx, cy, MountCentreX, MountCentreY);

// and the distance
dist = JG_GetDistanceBetweenPoints( cx, cy, MountCentreX, MountCentreY);

// trace from the centre at 1 degree intervals to buld arc offsets
for( a=0; a<256; ++a)
{
TraceX = cx;
TraceY = cy;

// rotate bearing
TraceBearing = bear + a;

// trace the offsets from centre on the rotated bearing
JG_MoveForwardOnPlane( &TraceX, &TraceY, TraceBearing, dist);

// assign new values as offsets (simply add to objects coords for the real coords)
r->WeaponMounts[ i].MountCentreOffsetsX[a] = TraceX;
r->WeaponMounts[ i].MountCentreOffsetsY[a] = TraceY;
}


// *************************************************************
// ** calculate firing point offsets (from mount centre) **

// get the centre of the mount bitmap (half width/height)
MountCentreX = M_SPRITEN_W( DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].SpriteNumber, 0) / 2;
MountCentreY = M_SPRITEN_H( DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].SpriteNumber, 0) / 2;

// get the bearing from the mount's centre to the firing coords
bear = JG_GetBearing(
MountCentreX, MountCentreY,
DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].FireX,
DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].FireY);

// and the distance
dist = JG_GetDistanceBetweenPoints(
MountCentreX, MountCentreY,
DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].FireX,
DAT_LoadedWeapons.weapons[ r->WeaponMounts[ i].a_WeaponNumber].FireY);

// trace from the mount centre at 1 degree intervals to buld firing pos offsets
for( a=0; a<256; ++a)
{
TraceX = MountCentreX;
TraceY = MountCentreY;

// rotate bearing
TraceBearing = bear + a;

// trace the offsets from centre on the rotated bearing
JG_MoveForwardOnPlane( &TraceX, &TraceY, TraceBearing, dist);

// assign new values as offsets (simply add to objects coords for the real coords)
r->WeaponMounts[ i].MountCentreToFirePosOffsetsX[a] = TraceX - MountCentreX;
r->WeaponMounts[ i].MountCentreToFirePosOffsetsY[a] = TraceY - MountCentreY;
}

}

fclose( f);

// validate ObjectClass
if( (r->ObjectClass < 0) || ( r->ObjectClass >= NUM_OBJECT_CLASSES) )
r->ObjectClass = OC_INFANTRY;

// validate vehicle
if( (r->vehicle < 0) || (r->vehicle >= NUM_VEHICLE_TYPES) )
r->vehicle = VT_NONE;

// validate crew count
if( r->DefaultCrewCount < 0)
r->DefaultCrewCount = 0;

// calc sound names
r->a_DestroyedSoundNumber = AUD_GetSoundNumberForName( r->DestroyedSoundName);
r->a_RandomSoundNumber = AUD_GetSoundNumberForName( r->RandomSoundName);
r->a_HooterSoundNumber = AUD_GetSoundNumberForName( r->HooterSoundName);
r->a_HurtSoundNumber = AUD_GetSoundNumberForName( r->HurtSoundName);
r->a_EnterSoundNumber = AUD_GetSoundNumberForName( r->EnterSoundName);
r->a_ExitSoundNumber = AUD_GetSoundNumberForName( r->ExitSoundName);

return 1;
}


Edited: 19 August 2008 01:38


You need to login to create posts in this thread.

Canuck

Joined: 31 August 2007
Posts: 419
19 August 2008 03:52 (UK time)

'Snippet'?

You must get tired of people asking if the need to reload can be eliminated. Actually, you can reduce the number of reloads to make an object if you do it like this:

1) Make graphics for object, projectile, weapon
2) Load game; make sprites for object, projectile, weapon
3) Make object, weapon and projectile
4) login to create posts in this thread.



Forums system (C) 1999-2023 by James Bunting.

Terms of Use