MuckyFoot-UrbanChaos/fallen/Source/elev.cpp
2017-05-20 11:14:17 +10:00

3437 lines
68 KiB
C++

//
// The new ECTS level stuff!
//
//
// Richard Reed's phone number in London, Hilton. 0171 636 1000 (room 343)
// 482874 for Bjarne at EA.
//
// Jez - 07771 780 630, 01483 573 849
// Darran - 01483 453085 07788 747 600
// Glenn - 07887 515577
//
#include "game.h"
#ifndef PSX
#include "ddlib.h"
#else
#define ZeroMemory(a,s) memset((UBYTE*)a,0,s)
SLONG PSX_eog_timer;
extern SLONG MFX_OnKey,MFX_OffKey;
#endif
#include "eway.h"
#include "mission.h"
#include "night.h"
#include "ob.h"
#include "trip.h"
#include "music.h"
#include "dirt.h"
#include "fog.h"
#include "hook.h"
#include "mist.h"
#include "water.h"
#include "puddle.h"
#include "az.h"
#include "drip.h"
#include "bang.h"
#include "glitter.h"
#include "spark.h"
#include "io.h"
#include "pow.h"
#include "build2.h"
#ifndef TARGET_DC
#include "es.h"
#endif
#include "ns.h"
#include "road.h"
#include "mav.h"
#include "cnet.h"
#include "interfac.h"
#include "animtmap.h"
#include "shadow.h"
#include "attract.h"
#include "cam.h"
#include "psystem.h"
#include "tracks.h"
#include "pcom.h"
#include "wmove.h"
#include "balloon.h"
#include "wand.h"
#include "ribbon.h"
#include "barrel.h"
#include "fc.h"
#include "briefing.h"
#include "ware.h"
#include "memory.h"
#include "playcuts.h"
#include "grenade.h"
#include "env.h"
#ifndef PSX
#include "panel.h"
#endif
#include "sound.h"
#ifdef USE_A3D
#include "soundenv.h"
#endif
#include "DCLowLevel.h"
#ifdef PSX
//
// PSX include
//
#include "libsn.h"
#include "psxeng.h"
#define MFFileHandle SLONG
#define FILE_OPEN_ERROR (-1)
#define SEEK_MODE_CURRENT (1)
extern SLONG SpecialOpen(CBYTE *name);
extern SLONG SpecialRead(SLONG handle,UBYTE *ptr,SLONG s1);
extern SLONG SpecialSeek(SLONG handle,SLONG mode,SLONG size);
extern SLONG SpecialClose(SLONG handle);
#define FileOpen(x) SpecialOpen(x)
#define FileClose(x) SpecialClose(x)
#define FileCreate(x,y) ASSERT(0)
#define FileRead(h,a,s) SpecialRead(h,(char*)a,s)
#define FileWrite(h,a,s) ASSERT(0)
#define FileSeek(h,m,o) SpecialSeek(h,m,o)
#ifdef PSX
CBYTE *psx_game_name;
#endif
#define FILE_CLOSE_ERROR ((MFFileHandle)-101)
#define FILE_CREATION_ERROR ((MFFileHandle)-102)
#define FILE_SIZE_ERROR ((SLONG)-103)
#define FILE_READ_ERROR ((SLONG)-104)
#define FILE_WRITE_ERROR ((SLONG)-105)
#define FILE_SEEK_ERROR ((SLONG)-106)
#define FILE_LOAD_AT_ERROR ((SLONG)-107)
//
// psx has no sewers at the moment
//
SLONG ES_load(CBYTE *filename)
{
return(0);
}
void ES_build_sewers(void)
{
}
#endif
#ifndef PSX
//
// This is the last map to be loaded.
//
CBYTE ELEV_last_map_loaded[MAX_PATH];
#ifdef MIKE
MFFileHandle llog_handle = NULL;
extern TCHAR *witem_strings[];
void TesterText(CBYTE *error, ...)
{
CBYTE buf[512];
va_list argptr;
if(!llog_handle)
{
llog_handle = FileCreate("tester.log",1);
if(llog_handle==FILE_CREATION_ERROR)
llog_handle = NULL;
}
if(llog_handle)
{
va_start(argptr,error);
vsprintf(buf, error,argptr);
va_end(argptr);
FileWrite(llog_handle,buf,strlen(buf));
}
}
#endif
#endif
//
// to stop psx stack overflow
//
#ifndef PSX
#ifndef TARGET_DC
extern UBYTE vehicle_random[];
CBYTE junk[2048];
EventPoint event_point;
extern SLONG save_psx;
SLONG iamapsx=0;
void ELEV_load_level(CBYTE *fname_level)
{
SLONG i;
SLONG j;
SLONG x;
SLONG z;
SLONG tx;
SLONG ty;
SLONG tz;
SLONG angle;
SLONG version;
SLONG load_ok = FALSE;
SLONG flag;
SLONG ew_id;
SLONG ew_type;
SLONG ew_subtype;
SLONG ew_world_x;
SLONG ew_world_y;
SLONG ew_world_z;
SLONG ew_active;
SLONG ew_active_arg;
SLONG ew_stay;
SLONG ew_stay_arg;
SLONG ew_colour;
SLONG ew_group;
SLONG ew_yaw;
SLONG ew_speed;
SLONG ew_delay;
SLONG mess_count = 0;
SLONG cutscene_count = 0;
SLONG water_level = -0x80;
MFFileHandle handle = NULL;
CBYTE *error;
SLONG enemy_type;
SLONG enemy_count;
SLONG follow;
SLONG kludge_index;
EWAY_Conddef ecd;
EWAY_Conddef ecd1;
EWAY_Conddef ecd2;
EWAY_Do ed;
EWAY_Stay es;
EWAY_Edef ee;
OB_Info *oi;
UBYTE FAKE_CARS = 0;
//
// Clear all waypoint info.
//
GAME_TURN=0;
SAVE_VALID=0;
EWAY_init();
iamapsx=ENV_get_value_number("iamapsx", FALSE);
//
// Start off with no players.
//
if(!CNET_network_game)
NO_PLAYERS = 0;
//
// Load the level.
//
load_ok = TRUE;
if (fname_level != NULL)
{
handle = FileOpen(fname_level);
if (handle == FILE_OPEN_ERROR)
{
//
// Couldn't open file.
//
load_ok = FALSE;
}
else
{
//
// Load in the mission file.
//
if (FileRead(handle, &version, sizeof(SLONG)) == FILE_READ_ERROR) goto file_error; // Version
if (FileRead(handle, &flag, sizeof(SLONG)) == FILE_READ_ERROR) goto file_error; // Used
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // BriefName
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // LightMapName
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // MapName
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // MissionName
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // SewerMapName
if (FileRead(handle, junk, sizeof(UWORD)) == FILE_READ_ERROR) goto file_error; // MapIndex... what's this?
if (FileRead(handle, junk, sizeof(UWORD)) == FILE_READ_ERROR) goto file_error; // Used
if (FileRead(handle, junk, sizeof(UWORD)) == FILE_READ_ERROR) goto file_error; // Free
GAME_FLAGS &= ~GF_SHOW_CRIMERATE;
GAME_FLAGS &= ~GF_CARS_WITH_ROAD_PRIMS;
if (flag & MISSION_FLAG_SHOW_CRIMERATE ) {GAME_FLAGS |= GF_SHOW_CRIMERATE ;}
if (flag & MISSION_FLAG_CARS_WITH_ROAD_PRIMS) {GAME_FLAGS |= GF_CARS_WITH_ROAD_PRIMS;}
//
// Two bytes of crime rate and padding...
//
if (FileRead(handle, junk, sizeof(UWORD)) == FILE_READ_ERROR) goto file_error; // Crime rate byte / Padding byte
CRIME_RATE = junk[0];
if (CRIME_RATE == 0)
{
//
// If the mission hasn't been given a crime rate.
//
CRIME_RATE = 50;
}
//#ifdef EIDOS
FAKE_CIVS = junk[1];// = 0;
extern UBYTE build_dc;
if(save_psx)
{
FAKE_CIVS >>=1;
if(FAKE_CIVS>3)
FAKE_CIVS=3;
}
else
if (build_dc)
{
FAKE_CIVS *= 2;
FAKE_CIVS /= 3;
}
else
{
if(!the_display.CurrDevice->IsHardware())
{
if(FAKE_CIVS>5)
FAKE_CIVS=5;
}
}
for(i=0;i<FAKE_CIVS;i++)
{
SLONG index;
SLONG mx,mz;
//
// lets hope the player isnt looking at the edge of the map
//
SLONG max = 0;
while(max++ < 128 * 128)
{
SLONG WAND_find_good_start_point_near(SLONG *mapx,SLONG *mapz);
mx=(Random()%100)+14;
mz=(Random()%100)+14;
if(WAND_find_good_start_point_near(&mx,&mz))
break;
}
index=PCOM_create_person(
PERSON_CIV,
0,
0,
PCOM_AI_CIV,
0,
0,
PCOM_MOVE_WANDER,
0,
0, // bent
0, // has
0, // drop
0, // zone
mx<<8,//0x10000,//darci->WorldPos.X + 0x4000,
0,//0x10000,//darci->WorldPos.Y,
mz<<8,//0x10000,//darci->WorldPos.Z,
0,
0,0,FLAG2_PERSON_FAKE_WANDER);
TO_THING(index)->Genus.Person->InsideRoom=(Random()%20)+20;
}
//#endif
//
// Load in all the eventpoints.
//
for (i = 0; i < MAX_EVENTPOINTS; i++)
{
if (FileRead(handle, &event_point, 14) == FILE_READ_ERROR) goto file_error;
if (FileRead(handle, &event_point.Data[0], 14*4+4) == FILE_READ_ERROR) goto file_error;
if (event_point.Used)
{
//
// Create a blank definitions to start off with.
//
ecd.type = EWAY_COND_TRUE;
ecd.negate = (event_point.Flags>>1)&1;
ecd.arg1 = 0;
ecd.arg2 = 0;
ecd.bool_arg1 = NULL;
ecd.bool_arg2 = NULL;
es.type = EWAY_STAY_ALWAYS;
es.arg = 0;
ed.type = EWAY_DO_NOTHING;
ed.subtype = 0;
ed.arg1 = 0;
ed.arg2 = 0;
ee.pcom_ai = 0;
ee.pcom_bent = 0;
ee.pcom_move = 0;
ee.pcom_has = 0;
ee.ai_other = 0;
ee.zone = 0;
kludge_index = 0;
//
// Convert from the mission editor eventpoint definition to the
// game waypoint stuff.
//
ew_colour = event_point.Colour;
ew_group = event_point.Group;
ew_world_x = event_point.X;
if (event_point.Flags&WPT_FLAGS_INSIDE) {
ew_world_y = get_inside_alt(event_point.Y);
} else {
ew_world_y = event_point.Y;
}
ew_world_z = event_point.Z;
ew_yaw = ((128+event_point.Direction) << 3) & 2047;
//
// This is how a waypoint is activated.
//
switch(event_point.TriggeredBy)
{
case TT_NONE:
break;
case TT_DEPENDENCY:
ecd.type = EWAY_COND_DEPENDENT;
ecd.arg1 = event_point.EPRef;
break;
case TT_RADIUS:
ecd.type = EWAY_COND_PROXIMITY;
ecd.arg1 = event_point.Radius;
break;
case TT_DOOR:
break;
case TT_TRIPWIRE:
ecd.type = EWAY_COND_TRIPWIRE;
break;
case TT_PRESSURE_PAD:
ecd.type = EWAY_COND_PRESSURE;
break;
case TT_ELECTRIC_FENCE:
break;
case TT_WATER_LEVEL:
break;
case TT_SECURITY_CAMERA:
ecd.type = EWAY_COND_CAMERA;
break;
case TT_SWITCH:
ecd.type = EWAY_COND_SWITCH;
break;
case TT_ANIM_PRIM:
break;
case TT_TIMER:
ecd.type = EWAY_COND_TIME;
ecd.arg1 = event_point.Radius; // Radius is the time for time triggers.
break;
case TT_SHOUT_ALL:
break;
case TT_BOOLEANAND:
//
// Booleans are always dependencies.
//
ecd1.type = EWAY_COND_DEPENDENT;
ecd1.arg1 = event_point.EPRef;
ecd1.negate = FALSE;
ecd2.type = EWAY_COND_DEPENDENT;
ecd2.arg1 = event_point.EPRefBool;
ecd2.negate = FALSE;
ecd.type = EWAY_COND_BOOL_AND;
ecd.bool_arg1 = &ecd1;
ecd.bool_arg2 = &ecd2;
break;
case TT_BOOLEANOR:
//
// Booleans are always dependencies.
//
ecd1.type = EWAY_COND_DEPENDENT;
ecd1.arg1 = event_point.EPRef;
ecd1.negate = FALSE;
ecd2.type = EWAY_COND_DEPENDENT;
ecd2.arg1 = event_point.EPRefBool;
ecd2.negate = FALSE;
ecd.type = EWAY_COND_BOOL_OR;
ecd.bool_arg1 = &ecd1;
ecd.bool_arg2 = &ecd2;
break;
case TT_ITEM_HELD:
ecd.type = EWAY_COND_ITEM_HELD;
ecd.arg1 = event_point.EPRef;
break;
case TT_ITEM_SEEN:
break;
case TT_KILLED:
ecd.type = EWAY_COND_PERSON_DEAD;
ecd.arg1 = event_point.EPRef;
break;
case TT_SHOUT_ANY:
break;
case TT_COUNTDOWN:
ecd.type = EWAY_COND_COUNTDOWN;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius;
break;
case TT_ENEMYRADIUS:
ecd.type = EWAY_COND_PERSON_NEAR;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius / 64;
break;
case TT_VISIBLECOUNTDOWN:
ecd.type = EWAY_COND_COUNTDOWN_SEE;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius;
break;
case TT_CUBOID:
ecd.type = EWAY_COND_PLAYER_CUBOID;
ecd.arg1 = event_point.Radius & 0xffff;
ecd.arg2 = event_point.Radius >> 16;
break;
case TT_HALFDEAD:
ecd.type = EWAY_COND_HALF_DEAD;
ecd.arg1 = event_point.EPRef;
break;
case TT_PERSON_SEEN:
ecd.type = EWAY_COND_A_SEE_B;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.EPRefBool;
break;
case TT_PERSON_USED:
ecd.type = EWAY_COND_PERSON_USED;
ecd.arg1 = event_point.EPRef;
break;
case TT_PLAYER_USES_RADIUS:
ecd.type = EWAY_COND_RADIUS_USED;
ecd.arg1 = event_point.Radius;
break;
case TT_GROUPDEAD:
ecd.type = EWAY_COND_GROUP_DEAD;
break;
case TT_PRIM_DAMAGED:
ecd.type = EWAY_COND_PRIM_DAMAGED;
break;
case TT_PERSON_ARRESTED:
ecd.type = EWAY_COND_PERSON_ARRESTED;
ecd.arg1 = event_point.EPRef;
break;
case TT_CONVERSATION_OVER:
ecd.type = EWAY_COND_CONVERSE_END;
ecd.arg1 = event_point.EPRef;
break;
case TT_COUNTER:
ecd.type = EWAY_COND_COUNTER_GTEQ;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius;
break;
case TT_KILLED_NOT_ARRESTED:
ecd.type = EWAY_COND_KILLED_NOT_ARRESTED;
ecd.arg1 = event_point.EPRef;
break;
case TT_CRIME_RATE_ABOVE:
ecd.type = EWAY_COND_CRIME_RATE_GTEQ;
ecd.arg1 = event_point.Radius / 100;
break;
case TT_CRIME_RATE_BELOW:
ecd.type = EWAY_COND_CRIME_RATE_LTEQ;
ecd.arg1 = event_point.Radius / 100;
break;
case TT_PERSON_IS_MURDERER:
ecd.type = EWAY_COND_IS_MURDERER;
ecd.arg1 = event_point.EPRef;
break;
case TT_PERSON_IN_VEHICLE:
ecd.type = EWAY_COND_PERSON_IN_VEHICLE;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.EPRefBool;
break;
case TT_THING_RADIUS_DIR:
ecd.type = EWAY_COND_THING_RADIUS_DIR;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius / 64;
break;
case TT_SPECIFIC_ITEM_HELD:
ecd.type = EWAY_COND_SPECIFIC_ITEM_HELD;
ecd.arg1 = event_point.EPRef;
break;
case TT_RANDOM:
ecd.type = EWAY_COND_RANDOM;
ecd.arg1 = event_point.EPRef;
break;
case TT_PLAYER_FIRES_GUN:
ecd.type = EWAY_COND_PLAYER_FIRED_GUN;
break;
case TT_DARCI_GRABBED:
ecd.type = EWAY_COND_DARCI_GRABBED;
break;
case TT_PUNCHED_AND_KICKED:
ecd.type = EWAY_COND_PUNCHED_AND_KICKED;
ecd.arg1 = event_point.EPRef;
break;
case TT_MOVE_RADIUS_DIR:
ecd.type = EWAY_COND_MOVE_RADIUS_DIR;
ecd.arg1 = event_point.EPRef;
ecd.arg2 = event_point.Radius / 64;
break;
default:
ASSERT(0);
break;
}
//
// This is what the waypoint does when its activated.
//
switch(event_point.WaypointType)
{
case WPT_NONE:
break;
case WPT_SIMPLE:
ed.type = EWAY_DO_NOTHING;
ed.arg1 = event_point.Data[0];
break;
case WPT_CREATE_PLAYER:
ed.type = EWAY_DO_CREATE_PLAYER;
switch(event_point.Data[0])
{
default:
case PT_DARCI:
ed.subtype = PLAYER_DARCI;
break;
case PT_ROPER:
ed.subtype = PLAYER_ROPER;
break;
case PT_COP:
ed.subtype = PLAYER_COP;
break;
case PT_GANG:
ed.subtype = PLAYER_THUG;
break;
}
ed.subtype |= (event_point.Data[1] ? 8 : 0);
break;
case WPT_CREATE_ENEMIES:
ed.type = EWAY_DO_CREATE_ENEMY;
if (version >= 3)
{
enemy_type = event_point.Data[0] & 0xffff;
enemy_count = event_point.Data[0] >> 16;
follow = event_point.Data[1];
}
else
{
enemy_type = event_point.Data[0];
enemy_count = event_point.Data[1];
follow = NULL;
}
//
// The HIWORD of Data[2] contains the HAS_* flags.
//
ee.pcom_has = 0;
if ((event_point.Data[2] >> 16) & HAS_PISTOL) {ee.pcom_has |= PCOM_HAS_GUN;}
if ((event_point.Data[2] >> 16) & HAS_SHOTGUN) {ee.pcom_has |= PCOM_HAS_SHOTGUN;}
if ((event_point.Data[2] >> 16) & HAS_AK47) {ee.pcom_has |= PCOM_HAS_AK47;}
if ((event_point.Data[2] >> 16) & HAS_GRENADE) {ee.pcom_has |= PCOM_HAS_GRENADE;}
if ((event_point.Data[2] >> 16) & HAS_BALLOON) {ee.pcom_has |= PCOM_HAS_BALLOON;}
if ((event_point.Data[2] >> 16) & HAS_KNIFE) {ee.pcom_has |= PCOM_HAS_KNIFE;}
if ((event_point.Data[2] >> 16) & HAS_BAT) {ee.pcom_has |= PCOM_HAS_BASEBALLBAT;}
switch(enemy_type)
{
case ET_CIV:
ed.subtype = PERSON_CIV;
break;
case ET_CIV_BALLOON:
ed.subtype = PERSON_CIV;
ee.pcom_has |= PCOM_HAS_BALLOON;
break;
case ET_SLAG:
ed.subtype = PERSON_SLAG_TART;
break;
case ET_UGLY_FAT_SLAG:
ed.subtype = PERSON_SLAG_FATUGLY;
break;
case ET_WORKMAN:
ed.subtype = PERSON_MECHANIC;
break;
case ET_GANG_RASTA:
ed.subtype = PERSON_THUG_RASTA;
break;
case ET_GANG_RED:
ed.subtype = PERSON_THUG_RED;
break;
case ET_GANG_GREY:
ed.subtype = PERSON_THUG_GREY;
break;
case ET_GANG_RASTA_PISTOL:
ed.subtype = PERSON_THUG_RASTA;
ee.pcom_has |= PCOM_HAS_GUN;
break;
case ET_GANG_RED_SHOTGUN:
ed.subtype = PERSON_THUG_RED;
ee.pcom_has |= PCOM_HAS_SHOTGUN;
break;
case ET_GANG_GREY_AK47:
ed.subtype = PERSON_THUG_GREY;
ee.pcom_has |= PCOM_HAS_AK47;
break;
case ET_COP:
ed.subtype = PERSON_COP;
break;
case ET_COP_PISTOL:
ed.subtype = PERSON_COP;
ee.pcom_has |= PCOM_HAS_GUN;
break;
case ET_COP_SHOTGUN:
ed.subtype = PERSON_COP;
ee.pcom_has |= PCOM_HAS_SHOTGUN;
break;
case ET_COP_AK47:
ed.subtype = PERSON_COP;
ee.pcom_has |= PCOM_HAS_AK47;
break;
case ET_HOSTAGE:
ed.subtype = PERSON_HOSTAGE;
break;
case ET_WORKMAN_GRENADE:
ed.subtype = PERSON_MECHANIC;
ee.pcom_has |= PCOM_HAS_GRENADE;
break;
case ET_TRAMP:
ed.subtype = PERSON_TRAMP;
break;
case ET_MIB1:
ed.subtype = PERSON_MIB1;
break;
case ET_MIB2:
ed.subtype = PERSON_MIB2;
break;
case ET_MIB3:
ed.subtype = PERSON_MIB3;
break;
case ET_NONE:
ed.subtype = PERSON_CIV;
break;
case ET_DARCI:
ed.subtype = PERSON_DARCI;
break;
case ET_ROPER:
ed.subtype = PERSON_ROPER;
break;
default:
ASSERT(0);
break;
}
ee.pcom_ai = LOWORD(event_point.Data[5]);
ee.ai_skill = HIWORD(event_point.Data[5]);
ee.pcom_bent = event_point.Data[4];
ee.pcom_move = event_point.Data[3] + 1;
ee.ai_other = event_point.Data[7] & 0xffff; // For PCOM_AI_BODYGUARD and PCOM_AI_ASSASIN, the ID of the waypoint that creates the person you guard/kill
ee.follow = follow; // For PCOM_MOVE_FOLLOW
ee.zone = event_point.Data[4] >> 8;
extern SWORD people_types[50];
people_types[ed.subtype]++;
if (ed.subtype == PERSON_MIB1 ||
ed.subtype == PERSON_MIB2 ||
ed.subtype == PERSON_MIB3)
{
//
// MIB never have a low skill...
//
ee.ai_skill = 8 + (ee.ai_skill >> 1);
}
if (ee.pcom_ai == PCOM_AI_FIGHT_TEST)
{
//
// The other is the combat move that knocks out this person.
//
ee.ai_other = event_point.Data[7] >> 16;
//
// Fight test dummies are always invulnerable.
//
ee.zone |= 1 << 4; // ugh!
}
//
// What does this person drop when he dies?
//
ee.drop = 0;
for (j = 0; j < 32; j++)
{
if (event_point.Data[8] & (1 << j))
{
ee.drop = j + 1;
}
}
break;
case WPT_CREATE_VEHICLE:
ed.type = EWAY_DO_CREATE_VEHICLE;
ed.arg1 = 0;
//
// What key to unlock the vehicle?
//
switch(event_point.Data[3])
{
case VK_UNLOCKED: ed.arg1 = SPECIAL_NONE; break;
case VK_RED: ed.arg1 = SPECIAL_KEY; break;
case VK_BLUE: ed.arg1 = SPECIAL_KEY; break;
case VK_GREEN: ed.arg1 = SPECIAL_KEY; break;
case VK_BLACK: ed.arg1 = SPECIAL_KEY; break;
case VK_WHITE: ed.arg1 = SPECIAL_KEY; break;
case VK_LOCKED: ed.arg1 = SPECIAL_NUM_TYPES; break; // A special that doesn't exist
default:
ASSERT(0);
break;
}
switch(event_point.Data[0])
{
case VT_NONE:
case VT_CAR:
ed.subtype = EWAY_SUBTYPE_VEHICLE_CAR;
break;
case VT_VAN:
ed.subtype = EWAY_SUBTYPE_VEHICLE_VAN;
break;
case VT_TAXI:
ed.subtype = EWAY_SUBTYPE_VEHICLE_TAXI;
break;
case VT_HELICOPTER:
ed.subtype = EWAY_SUBTYPE_VEHICLE_HELICOPTER;
if (event_point.Data[1] == VMT_TRACK_TARGET)
{
//
// arg2 is who to track... for a helicopter.
//
ed.arg2 = event_point.Data[2];
}
break;
case VT_BIKE:
ed.subtype = EWAY_SUBTYPE_VEHICLE_BIKE;
break;
case VT_POLICE:
ed.subtype = EWAY_SUBTYPE_VEHICLE_POLICE;
break;
case VT_AMBULANCE:
ed.subtype = EWAY_SUBTYPE_VEHICLE_AMBULANCE;
break;
case VT_JEEP:
ed.subtype = EWAY_SUBTYPE_VEHICLE_JEEP;
break;
case VT_MEATWAGON:
ed.subtype = EWAY_SUBTYPE_VEHICLE_MEATWAGON;
break;
case VT_SEDAN:
ed.subtype = EWAY_SUBTYPE_VEHICLE_SEDAN;
break;
case VT_WILDCATVAN:
ed.subtype = EWAY_SUBTYPE_VEHICLE_WILDCATVAN;
break;
default:
ASSERT(0);
break;
}
break;
case WPT_CREATE_ITEM:
if (version < 4)
{
//
// This is using the old list of hundreds of items.
//
event_point.Data[0] = IT_PISTOL;
}
ed.type = EWAY_DO_CREATE_ITEM;
ed.arg1 = event_point.Data[2]; // flags
#ifdef MIKE
if(!(ed.arg1&EWAY_ARG_ITEM_FOLLOW_PERSON))
{
switch(event_point.Data[0])
{
case IT_BARREL:
break;
case 0:
break;
default:
TesterText("(WP)%d item %s at %d,%d,%d \n",i,witem_strings[event_point.Data[0]-1],event_point.X>>8,event_point.Y>>8,event_point.Z>>8);
break;
}
}
#endif
switch(event_point.Data[0])
{
default:
case IT_NONE:
case IT_KEY: ed.subtype = SPECIAL_KEY; break;
case IT_PISTOL: ed.subtype = SPECIAL_GUN; break;
case IT_HEALTH: ed.subtype = SPECIAL_HEALTH; break;
case IT_SHOTGUN: ed.subtype = SPECIAL_SHOTGUN; break;
case IT_KNIFE: ed.subtype = SPECIAL_KNIFE; break;
case IT_AK47: ed.subtype = SPECIAL_AK47; break;
case IT_MINE: ed.subtype = SPECIAL_MINE; break;
case IT_BASEBALLBAT: ed.subtype = SPECIAL_BASEBALLBAT; break;
case IT_AMMO_SHOTGUN: ed.subtype = SPECIAL_AMMO_SHOTGUN; break;
case IT_AMMO_AK47: ed.subtype = SPECIAL_AMMO_AK47; break;
case IT_AMMO_PISTOL: ed.subtype = SPECIAL_AMMO_PISTOL; break;
case IT_KEYCARD: ed.subtype = SPECIAL_KEYCARD; break;
case IT_FILE: ed.subtype = SPECIAL_FILE; break;
case IT_FLOPPY_DISK: ed.subtype = SPECIAL_FLOPPY_DISK; break;
case IT_CROWBAR: ed.subtype = SPECIAL_CROWBAR; break;
case IT_VIDEO: ed.subtype = SPECIAL_VIDEO; break;
case IT_GLOVES: ed.subtype = SPECIAL_GLOVES; break;
case IT_WEEDAWAY: ed.subtype = SPECIAL_WEEDAWAY; break;
case IT_GRENADE: ed.subtype = SPECIAL_GRENADE; break;
case IT_EXPLOSIVES: ed.subtype = SPECIAL_EXPLOSIVES; break;
case IT_WIRE_CUTTER:
ed.type = EWAY_DO_END_OF_WORLD;
break;
case IT_BARREL:
//
// Don't create a waypoint- just put down some barrels.
//
for (j = 0; j < event_point.Data[1]; j++)
{
BARREL_alloc(
BARREL_TYPE_NORMAL,
PRIM_OBJ_BARREL,
ew_world_x + (Random() & 0xf) - 0x7,
ew_world_z + (Random() & 0xf) - 0x7,
NULL);
}
goto dont_create_a_waypoint;
}
break;
case WPT_CREATE_CREATURE:
ed.type = EWAY_DO_CREATE_ANIMAL;
ed.subtype = event_point.Data[0];
break;
case WPT_CREATE_CAMERA:
ed.type = EWAY_DO_CAMERA_CREATE;
ew_speed = event_point.Data[2] >> 2;
ew_delay = event_point.Data[3];
SATURATE(ew_speed, 4, 255);
ed.arg1 = ew_speed;
ed.arg2 = ew_delay;
ed.subtype = 0;
if (event_point.Data[4]) {ed.subtype |= EWAY_SUBTYPE_CAMERA_LOCK_PLAYER;}
if (event_point.Data[5]) {ed.subtype |= EWAY_SUBTYPE_CAMERA_LOCK_DIRECTION;}
if (event_point.Data[6]) {ed.subtype |= EWAY_SUBTYPE_CAMERA_CANT_INTERRUPT;}
break;
case WPT_CREATE_TARGET:
ed.type = EWAY_DO_CAMERA_TARGET;
switch(event_point.Data[1])
{
case NULL:
case CT_NORMAL:
ed.subtype = EWAY_SUBTYPE_CAMERA_TARGET_PLACE;
break;
case CT_ATTACHED:
ed.subtype = EWAY_SUBTYPE_CAMERA_TARGET_THING;
break;
case CT_NEAREST_LIVING:
ed.subtype = EWAY_SUBTYPE_CAMERA_TARGET_NEAR;
break;
default:
ASSERT(0);
break;
}
break;
case WPT_CREATE_MAP_EXIT:
break;
case WPT_CAMERA_WAYPOINT:
ed.type = EWAY_DO_CAMERA_WAYPOINT;
ew_speed = event_point.Data[2] >> 2;
ew_delay = event_point.Data[3];
if (ew_speed < 4) {ew_speed = 4;}
ed.arg1 = ew_speed;
ed.arg2 = ew_delay;
//
// 'Camera waypoint' waypoints must have this condition.
//
ecd.type = EWAY_COND_CAMERA_AT;
ecd.arg1 = NULL;
ecd.arg2 = NULL;
ecd.negate = FALSE;
break;
case WPT_TARGET_WAYPOINT:
break;
case WPT_MESSAGE:
ed.type = EWAY_DO_MESSAGE;
ed.arg1 = mess_count++;
ed.arg2 = event_point.Data[2];
ed.subtype = event_point.Data[1]; // The time the message lasts for.
break;
case WPT_NAV_BEACON:
ed.type = EWAY_DO_NAV_BEACON;
ed.arg1 = mess_count++;
ed.arg2 = event_point.Data[1];
break;
case WPT_SOUND_EFFECT:
ed.type = EWAY_DO_SOUND_EFFECT;
ed.subtype = event_point.Data[0];
ed.arg1 = event_point.Data[1];
break;
case WPT_VISUAL_EFFECT:
ed.type = EWAY_DO_EXPLODE;
ed.subtype = event_point.Data[0];
ed.arg1 = event_point.Data[1];
break;
case WPT_SPOT_EFFECT:
goto dont_create_a_waypoint;
/*
//
// These are automatically generated nowadays...
//
ed.type = EWAY_DO_SPOT_FX;
ed.subtype = event_point.Data[0];
ed.arg1 = event_point.Data[1];
*/
break;
case WPT_TELEPORT:
break;
case WPT_TELEPORT_TARGET:
break;
case WPT_END_GAME_LOSE:
ed.type = EWAY_DO_MISSION_FAIL;
break;
case WPT_END_GAME_WIN:
ed.type = EWAY_DO_MISSION_COMPLETE;
break;
case WPT_SHOUT:
break;
case WPT_ACTIVATE_PRIM:
switch(event_point.Data[0])
{
case AP_DOOR:
ed.type = EWAY_DO_CONTROL_DOOR;
break;
case AP_ELECTRIC_FENCE:
ed.type = EWAY_DO_ELECTRIFY_FENCE;
break;
case AP_SECURITY_CAMERA:
break;
default:
ASSERT(0);
break;
}
break;
case WPT_CREATE_TRAP:
ed.type = EWAY_DO_EMIT_STEAM;
ed.subtype = event_point.Data[4];
ed.arg1 = event_point.Data[3];
ed.arg2 = 0;
ed.arg2 |= (event_point.Data[1] & 0x3f) << 10;
ed.arg2 |= (event_point.Data[2] & 0x0f) << 6;
ed.arg2 |= (event_point.Data[5] & 0x3f) << 0;
break;
case WPT_ADJUST_ENEMY:
ed.type = EWAY_DO_CHANGE_ENEMY;
ed.arg1 = event_point.Data[6]; // ID of waypoint that creates the person to adjust
ee.pcom_ai = event_point.Data[5];
ee.pcom_bent = event_point.Data[4];
ee.pcom_move = event_point.Data[3] + 1;
ee.ai_other = event_point.Data[7]; // For PCOM_AI_BODYGUARD/PCOM_AI_ASSASIN, the ID of the waypoint that creates the person you guard.
if (ee.pcom_ai == PCOM_AI_FIGHT_TEST)
{
//
// The other is the combat move that knocks out this person.
//
ee.ai_other = event_point.Data[7] >> 16;
//
// Fight test dummies are always invulnerable.
//
ee.zone |= 1 << 4; // ugh!
}
if (version >= 3)
{
ee.follow = event_point.Data[1];
}
else
{
ee.follow = NULL;
}
break;
case WPT_ENEMY_FLAGS:
ed.type = EWAY_DO_CHANGE_ENEMY_FLG;
ed.arg1 = event_point.Data[0]; // ID of waypoint that creates the person to adjust
ed.arg2 = event_point.Data[4];
break;
case WPT_LINK_PLATFORM:
ed.type = EWAY_DO_CREATE_PLATFORM;
if (event_point.Data[0] == 0)
{
//
// Use default speed.
//
ed.arg1 = 50;
}
else
{
ed.arg1 = event_point.Data[0];
}
if (event_point.Data[1] & LP_LOCK_TO_AXIS) {ed.arg2 = PLAT_FLAG_LOCK_MOVE;}
if (event_point.Data[1] & LP_LOCK_ROTATION) {ed.arg2 = PLAT_FLAG_LOCK_ROT;}
if (event_point.Data[1] & LP_BODGE_ROCKET) {ed.arg2 = PLAT_FLAG_BODGE_ROCKET;}
break;
case WPT_CREATE_BOMB:
ed.type = EWAY_DO_CREATE_BOMB;
break;
case WPT_CREATE_BARREL:
{
UWORD barrel_type;
UWORD prim;
switch(event_point.Data[0])
{
case BT_OIL_DRUM:
extern SLONG playing_level(const CBYTE *name);
if (playing_level("Semtex.ucm"))
{
barrel_type = BARREL_TYPE_NORMAL;
prim = 145;
break;
}
else
{
//
// Fallthrough!
//
}
case BT_BARREL:
case BT_LOX_DRUM:
barrel_type = BARREL_TYPE_NORMAL;
prim = PRIM_OBJ_BARREL;
break;
case BT_TRAFFIC_CONE:
barrel_type = BARREL_TYPE_CONE;
prim = PRIM_OBJ_TRAFFIC_CONE;
break;
case BT_BURNING_BARREL:
barrel_type = BARREL_TYPE_BURNING;
prim = PRIM_OBJ_BARREL;
break;
case BT_BURNING_BIN:
case BT_BIN:
barrel_type = BARREL_TYPE_BIN;
prim = PRIM_OBJ_BIN;
break;
default:
ASSERT(0);
break;
}
if (!(event_point.Flags & WPT_FLAGS_REFERENCED) && ecd.type == EWAY_COND_TRUE)
{
BARREL_alloc(
barrel_type,
prim,
ew_world_x,
ew_world_z,
NULL);
goto dont_create_a_waypoint;
}
else
{
ed.type = EWAY_DO_CREATE_BARREL;
ed.subtype = barrel_type;
ed.arg2 = prim;
}
}
break;
case WPT_KILL_WAYPOINT:
ed.type = EWAY_DO_KILL_WAYPOINT;
ed.arg1 = event_point.Data[0];
break;
case WPT_CREATE_TREASURE:
ed.type = EWAY_DO_CREATE_ITEM;
ed.subtype = SPECIAL_TREASURE;
#ifdef MIKE
TesterText(" POWERUP at %d,%d,%d \n",event_point.X>>8,event_point.Y>>8,event_point.Z>>8);
#endif
break;
case WPT_BONUS_POINTS:
if (0)
{
//
// Bonus points are just messages nowadays.
//
ed.type = EWAY_DO_OBJECTIVE;
ed.subtype = EWAY_SUBTYPE_OBJECTIVE_SUB;
ed.arg1 = mess_count++;
ed.arg2 = event_point.Data[1] / 10;
}
else
{
ed.type = EWAY_DO_MESSAGE;
ed.arg1 = mess_count++;
ed.arg2 = NULL; // Who says the message
ed.subtype = 0; // The time the message lasts for.
}
break;
case WPT_GROUP_LIFE:
ed.type = EWAY_DO_GROUP_LIFE;
break;
case WPT_GROUP_DEATH:
ed.type = EWAY_DO_GROUP_DEATH;
break;
case WPT_CONVERSATION:
if (event_point.Data[3])
{
ed.type = EWAY_DO_AMBIENT_CONV;
}
else
{
ed.type = EWAY_DO_CONVERSATION;
}
ed.subtype = mess_count++;
ed.arg1 = event_point.Data[1];
ed.arg2 = event_point.Data[2];
break;
case WPT_INCREMENT:
ed.type = EWAY_DO_INCREASE_COUNTER;
ed.subtype = event_point.Data[1];
break;
case WPT_TRANSFER_PLAYER:
ed.type = EWAY_DO_TRANSFER_PLAYER;
ed.arg1 = event_point.Data[0];
break;
case WPT_AUTOSAVE:
ed.type = EWAY_DO_AUTOSAVE;
break;
case WPT_MAKE_SEARCHABLE:
//
// Look for the nearest ob and flag it as searchable.
//
{
OB_Info *oi = OB_find_index(
ew_world_x,
ew_world_y,
ew_world_z,
0x100,
FALSE);
if (oi)
{
OB_ob[oi->index].flags |= OB_FLAG_SEARCHABLE;
}
}
goto dont_create_a_waypoint;
case WPT_LOCK_VEHICLE:
ed.type = EWAY_DO_LOCK_VEHICLE;
ed.arg1 = event_point.Data[0];
if (event_point.Data[1])
{
ed.subtype = EWAY_SUBTYPE_VEHICLE_LOCK;
}
else
{
ed.subtype = EWAY_SUBTYPE_VEHICLE_UNLOCK;
}
break;
case WPT_CUT_SCENE:
{
ed.type = EWAY_DO_CUTSCENE;
ed.arg1 = cutscene_count++;
}
break;
case WPT_GROUP_RESET:
ed.type = EWAY_DO_GROUP_RESET;
break;
case WPT_COUNT_UP_TIMER:
ed.type = EWAY_DO_VISIBLE_COUNT_UP;
break;
case WPT_RESET_COUNTER:
ed.type = EWAY_DO_RESET_COUNTER;
ed.subtype = event_point.Data[0];
break;
case WPT_CREATE_MIST:
ed.type = EWAY_DO_CREATE_MIST;
break;
case WPT_STALL_CAR:
ed.type = EWAY_DO_STALL_CAR;
ed.arg1 = event_point.Data[0];
break;
case WPT_EXTEND:
ed.type = EWAY_DO_EXTEND_COUNTDOWN;
ed.arg1 = event_point.Data[0];
ed.arg2 = event_point.Data[1];
break;
case WPT_MOVE_THING:
ed.type = EWAY_DO_MOVE_THING;
ed.arg1 = event_point.Data[0];
break;
case WPT_MAKE_PERSON_PEE:
ed.type = EWAY_DO_MAKE_PERSON_PEE;
ed.arg1 = event_point.Data[0];
break;
case WPT_CONE_PENALTIES:
ed.type = EWAY_DO_CONE_PENALTIES;
break;
case WPT_SIGN:
ed.type = EWAY_DO_SIGN;
ed.arg1 = event_point.Data[0];
ed.arg2 = event_point.Data[1];
break;
case WPT_WAREFX:
ed.type = EWAY_DO_WAREFX;
ed.arg1 = event_point.Data[0];
break;
case WPT_NO_FLOOR:
ed.type = EWAY_DO_NO_FLOOR;
break;
case WPT_SHAKE_CAMERA:
ed.type = EWAY_DO_SHAKE_CAMERA;
break;
default:
ASSERT(0);
break;
}
switch(event_point.OnTrigger)
{
case OT_NONE:
case OT_ACTIVE:
es.type = EWAY_STAY_ALWAYS;
break;
case OT_ACTIVE_WHILE:
es.type = EWAY_STAY_WHILE;
break;
case OT_ACTIVE_TIME:
es.type = EWAY_STAY_TIME;
es.arg = event_point.AfterTimer;
break;
case OT_ACTIVE_DIE:
es.type = EWAY_STAY_DIE;
break;
default:
ASSERT(0);
break;
}
//
// Unreferenced when COND_PERSON DO_MESSAGE waypoints should
// be set to whenever triggered.
//
if (ecd.type == EWAY_COND_PERSON_USED &&
ed.type == EWAY_DO_MESSAGE)
{
if (!(event_point.Flags & WPT_FLAGS_REFERENCED))
{
es.type = EWAY_STAY_WHILE;
}
}
// if(0)
if (save_psx || ENV_get_value_number("iamapsx", FALSE))
{
//
// Skip waypoints marked as optional. We do it here so that
// the message numbers set properly.
//
if (event_point.Flags & WPT_FLAGS_OPTIONAL)
{
continue;
}
}
//
// Create the waypoint.
//
EWAY_create(
i,
ew_colour,
ew_group,
ew_world_x,
ew_world_y,
ew_world_z,
ew_yaw,
&ecd,
&ed,
&es,
&ee,
!(event_point.Flags & WPT_FLAGS_REFERENCED),
kludge_index,
event_point.Data[9]);
dont_create_a_waypoint:;
continue;
}
else
{
continue;
}
// abandon_waypoint:;
#ifndef PSX
#ifndef TARGET_DC
{
CBYTE title[256];
//
// Tell the user about not loading the waypoint.
//
sprintf(title, "Error loading waypoint %d", i);
MessageBox(
hDDLibWindow,
error,
title,
MB_OK | MB_ICONERROR | MB_APPLMODAL);
}
#endif
#endif
}
}
// skip the skill level junk
if (version>5)
FileSeek(handle,SEEK_MODE_CURRENT,254); // last one is now boredom rate...
FileRead(handle,&BOREDOM_RATE,1);
if (version<10) BOREDOM_RATE=4;
if(BOREDOM_RATE<4)
BOREDOM_RATE=4;
if (version>8)
{
// FileSeek(handle,SEEK_MODE_CURRENT,1);
FileRead(handle,&FAKE_CARS,1);
FileRead(handle,&MUSIC_WORLD,1);
if (MUSIC_WORLD<1) MUSIC_WORLD=1;
}
//
// Load in the messages and other extra data
//
if (version<8) { // only messages
for (i = 0; i < mess_count; i++)
{
SLONG l;
ZeroMemory(junk,sizeof(junk));
if (version>4) FileRead(handle,&l,4); else l=_MAX_PATH;
if (FileRead(handle, junk, l) == FILE_READ_ERROR) goto file_error;
//
// Tell the EWAY module what each message is.
//
EWAY_set_message(i, junk);
}
} else {
for (i = 0; i < mess_count+cutscene_count; i++)
{
SLONG l;
UBYTE what;
FileRead(handle,&what,1);
switch (what) {
case 1: // message
ZeroMemory(junk,sizeof(junk));
FileRead(handle,&l,4);
if (FileRead(handle, junk, l) == FILE_READ_ERROR) goto file_error;
//
// Tell the EWAY module what each message is.
//
EWAY_set_message(i, junk);
break;
case 2: // cutscene
//PLAYCUTS_cutscenes[PLAYCUTS_cutscene_ctr++]=PLAYCUTS_Read(handle);
PLAYCUTS_Read(handle); // don't care bout result -- static alloc
break;
}
}
}
if (version >= 2)
{
//
// Load in the zone squares.
//
for (x = 0; x < 128; x++)
{
if (FileRead(handle, junk, 128) == FILE_READ_ERROR) goto file_error;
for (z = 0; z < 128; z++)
{
PAP_2HI(x,z).Flags &= ~PAP_FLAG_ZONE1;
PAP_2HI(x,z).Flags &= ~PAP_FLAG_ZONE2;
PAP_2HI(x,z).Flags &= ~PAP_FLAG_ZONE3;
PAP_2HI(x,z).Flags &= ~PAP_FLAG_ZONE4;
if (junk[z] & ZF_ZONE1) {PAP_2HI(x,z).Flags |= PAP_FLAG_ZONE1;}
if (junk[z] & ZF_ZONE2) {PAP_2HI(x,z).Flags |= PAP_FLAG_ZONE2;}
if (junk[z] & ZF_ZONE3) {PAP_2HI(x,z).Flags |= PAP_FLAG_ZONE3;}
if (junk[z] & ZF_ZONE4) {PAP_2HI(x,z).Flags |= PAP_FLAG_ZONE4;}
if (junk[z] & ZF_NO_WANDER)
{
if (PAP_2HI(x,z).Flags & PAP_FLAG_HIDDEN)
{
//
// For hidden squares, the PAP_FLAG_WANDER flag means something else!
//
}
else
{
PAP_2HI(x,z).Flags &= ~PAP_FLAG_WANDER;
}
}
if (junk[z] & ZF_NO_GO)
{
void MAV_turn_off_whole_square(
SLONG x,
SLONG z);
void MAV_turn_off_whole_square_car(
SLONG x,
SLONG z);
MAV_turn_off_whole_square(x,z);
MAV_turn_off_whole_square_car(x,z);
PAP_2HI(x,z).Flags |= PAP_FLAG_NOGO;
}
else
{
PAP_2HI(x,z).Flags &= ~PAP_FLAG_NOGO;
}
}
}
}
//
// Finish with the file.
//
FileClose(handle);
//
// The music world is taken from this file now!
//
{
FILE *handle = MF_Fopen("levels\\mworlds.txt", "rb");
if (handle)
{
CBYTE line[256];
CBYTE levname[64];
SLONG match;
SLONG mworld;
CBYTE *ch;
CBYTE *blah;
for (ch = fname_level; *ch && *ch != '\\'; ch++);
ch += 1;
blah = levname;
while(*ch != '.')
{
*blah++ = *ch++;
}
*blah++ = ':';
*blah++ = ' ';
*blah++ = '%';
*blah++ = 'd';
*blah++ = '\000';
_strlwr(levname);
while(fgets(line, 256, handle))
{
_strlwr(line);
match = sscanf(line, levname, &mworld);
if (match == 1)
{
MUSIC_WORLD = mworld;
break;
}
}
MF_Fclose(handle);
}
}
//
// No more waypoints to be created.
//
EWAY_created_last_waypoint();
EWAY_work_out_which_ones_are_in_warehouses();
//
// create fake cars (must do this after the "real" cars are created)
//
extern SLONG WAND_find_good_start_point_for_car(SLONG* posx, SLONG* posz, SLONG* yaw, SLONG anywhere);
if(FAKE_CARS && save_psx)
{
FAKE_CARS=(FAKE_CARS+1)>>1;
}
else
if(FAKE_CARS)
if(!the_display.CurrDevice->IsHardware())
{
FAKE_CARS=(FAKE_CARS+1)>>1;
}
for (i = 0; i < FAKE_CARS; i++)
{
SLONG x,z,yaw;
SLONG watchdog;
watchdog = 16;
while (!WAND_find_good_start_point_for_car(&x, &z, &yaw, 1))
{
if (!--watchdog) break;
}
if (!watchdog) continue;
SLONG ix = PCOM_create_person(
PERSON_CIV,
0,
0,
PCOM_AI_DRIVER,
0,
0,
PCOM_MOVE_WANDER,
0,
0,
0,
0,
0,
x << 8,
0,
z << 8,
0,
0,
0,
FLAG2_PERSON_FAKE_WANDER);
TO_THING(ix)->Genus.Person->sewerbits = (Random()%20)+20;
SLONG type = (Random() >> 4) &15;//% (sizeof(vehicles) / sizeof(vehicles[0]));
SLONG p_index = VEH_create(
x << 8,
0,
z << 8,
yaw,
0,
0,
vehicle_random[type],
0,
Random());
WMOVE_create(TO_THING(p_index));
}
//
// Sort out the water-related flags.
//
for (x = 0; x < PAP_SIZE_LO; x++)
for (z = 0; z < PAP_SIZE_LO; z++)
{
PAP_2LO(x,z).water = PAP_LO_NO_WATER;
for (x = 1; x < PAP_SIZE_HI - 1; x++)
for (z = 1; z < PAP_SIZE_HI - 1; z++)
{
if (PAP_2HI(x,z).Flags & PAP_FLAG_WATER)
{
PAP_2HI(x + 0, z + 0).Flags |= PAP_FLAG_SINK_POINT| PAP_FLAG_WATER;
PAP_2HI(x + 1, z + 0).Flags |= PAP_FLAG_SINK_POINT;
PAP_2HI(x + 0, z + 1).Flags |= PAP_FLAG_SINK_POINT;
PAP_2HI(x + 1, z + 1).Flags |= PAP_FLAG_SINK_POINT;
//PAP_2HI(x - 1, z - 1).Flags |= PAP_FLAG_REFLECTIVE;
//PAP_2HI(x + 0, z - 1).Flags |= PAP_FLAG_REFLECTIVE;
//PAP_2HI(x + 1, z - 1).Flags |= PAP_FLAG_REFLECTIVE;
//PAP_2HI(x - 1, z + 0).Flags |= PAP_FLAG_REFLECTIVE;
//PAP_2HI(x - 1, z + 1).Flags |= PAP_FLAG_REFLECTIVE;
PAP_2LO(x >> 2, z >> 2).water = water_level >> 3; // Hard-coded water level.
}
}
for (x = 0; x < PAP_SIZE_LO - 1; x++)
for (z = 0; z < PAP_SIZE_LO - 1; z++)
{
//
// All watery obs at the water level.
//
for (oi = OB_find(x,z); oi->prim; oi += 1)
{
if (PAP_2HI(oi->x >> 8, oi->z >> 8).Flags & PAP_FLAG_WATER)
{
oi->y = water_level - get_prim_info(oi->prim)->miny;
}
}
}
}
}
else
{
file_error:;
load_ok = FALSE;
//
// Finish with the file.
//
if (handle)
{
FileClose(handle);
}
}
//
// If there was an error loading the level, then we just
// put down the player on a map.
//
if (!load_ok)
{
if(NO_PLAYERS==0)
NO_PLAYERS = 1;
/*
if(ShiftFlag)
NO_PLAYERS = 2; // sneak in an extra player
else
NO_PLAYERS = 1;
*/
//
// Plonk down the players.
//
x = 64 << 8;
z = 64 << 8;
//
// Initilaises the players.
//
for (i = 0; i < NO_PLAYERS; i++)
{
angle = (2048 * i) / NO_PLAYERS;
tx = x + (SIN(angle) >> 9);
tz = z + (COS(angle) >> 9);
ty = PAP_calc_height_at(tx,tz);
NET_PERSON(i) = create_player(
PLAYER_DARCI,
tx,ty,tz,
i);
}
}
else
{
void load_level_anim_prims(void);
load_level_anim_prims();
}
//
// the CRIME_RATE stuff is now done be EWAY_created_last_waypoint()
//
}
#endif
#endif
void save_dreamcast_wad(CBYTE *fname);
void load_dreamcast_wad(CBYTE *fname);
SLONG quick_load=0;
UBYTE loading_screen_active;
//
// Initialises the game using the given files.
// Any of the files can be NULL except the map file.
//
// The stuff that is common to DC and PC.
void ELEV_game_init_common(
CBYTE *fname_map,
CBYTE *fname_lighting,
CBYTE *fname_citsez,
CBYTE *fname_level)
{
extern void SND_BeginAmbient();
MFX_load_wave_list();
SND_BeginAmbient();
}
#ifdef TARGET_DC
//#if 1
SLONG ELEV_game_init(
CBYTE *fname_map,
CBYTE *fname_lighting,
CBYTE *fname_citsez,
CBYTE *fname_level)
{
SLONG i;
// Fix the language-specific stuff by loading the correct DAD file.
char cTempName[50];
ASSERT ( fname_level[0] == 'l' );
ASSERT ( fname_level[1] == 'e' );
ASSERT ( fname_level[2] == 'v' );
ASSERT ( fname_level[3] == 'e' );
ASSERT ( fname_level[4] == 'l' );
ASSERT ( fname_level[5] == 's' );
ASSERT ( fname_level[6] == '\\' );
switch ( ENV_get_value_number ( "lang_num", 0, "" ) )
{
case 0:
// English.
strcpy ( cTempName, "levels\\" );
break;
case 1:
// French.
strcpy ( cTempName, "levels_french\\" );
break;
default:
ASSERT ( FALSE );
break;
}
ASSERT ( strlen ( cTempName ) + strlen ( &(fname_level[7]) ) < 45 );
strcat ( cTempName, &(fname_level[7]) );
load_dreamcast_wad(cTempName);
init_user_interface();
ELEV_game_init_common ( fname_map, fname_lighting, fname_citsez, fname_level );
return TRUE;
}
#else
#if !defined(PSX)
SLONG ELEV_game_init(
CBYTE *fname_map,
CBYTE *fname_lighting,
CBYTE *fname_citsez,
CBYTE *fname_level)
{
SLONG i;
/*
extern UWORD darci_dlight;
darci_dlight = 0;
*/
ATTRACT_loadscreen_draw(10 * 256 / 100);
//
// Remember the last map loaded.
//
strcpy(ELEV_last_map_loaded, fname_map);
//
// Sets the prim arrays to be just after all the person points
// and faces.
//
// revert_to_prim_status();
//
// Marks all the prim_objects as unloaded.
//
mark_prim_objects_as_unloaded();
//
// Added by MikeD, anything could happen from here on in
//
void global_load(void);
global_load();
ATTRACT_loadscreen_draw(15 * 256 / 100);
//
// So we stay in synch!
//
extern SLONG kick_or_punch; // This is in person.cpp
kick_or_punch = 0;
//
// Initialise everything.
//
void init_anim_prims(void);
void init_overlay(void);
init_overlay();
WMOVE_init();
PCOM_init();
init_things();
init_draw_meshes();
// init_draw_tweens(); // this is in global_load()
init_anim_prims();
init_persons();
init_choppers();
init_pyros();
// init_furniture();
init_vehicles();
init_projectiles();
init_specials();
BAT_init();
void init_gangattack(void);
init_gangattack();
init_map();
init_user_interface();
ATTRACT_loadscreen_draw(20 * 256 / 100);
SOUND_reset();
PARTICLE_Reset();
// TRACKS_Reset();
TRACKS_InitOnce();
RIBBON_init();
#ifndef PSX
load_palette("data\\tex01.pal");
//
// The PC panel widescreen text...
//
extern CBYTE PANEL_wide_text[256];
extern THING_INDEX PANEL_wide_top_person;
extern THING_INDEX PANEL_wide_bot_person;
PANEL_wide_text[0] = 0;
PANEL_wide_top_person = NULL;
PANEL_wide_bot_person = NULL;
#endif
load_animtmaps();
ATTRACT_loadscreen_draw(25 * 256 / 100);
FC_init();
#ifdef BIKE
BIKE_init();
#endif
BARREL_init();
BALLOON_init();
NIGHT_init();
OB_init();
TRIP_init();
FOG_init();
MIST_init();
// WATER_init();
PUDDLE_init();
// AZ_init();
DRIP_init();
// BANG_init();
GLITTER_init();
POW_init();
SPARK_init();
CONSOLE_clear();
PLAT_init();
MAV_init();
PANEL_new_text_init();
ATTRACT_loadscreen_draw(35 * 256 / 100);
//
// static's in sound.cpp
//
void init_ambient(void);
init_ambient();
extern void MAP_beacon_init();
extern void MAP_pulse_init();
MAP_pulse_init();
MAP_beacon_init();
//
// Load the map.
//
load_game_map(fname_map);
calc_prim_info();
ATTRACT_loadscreen_draw(50 * 256 / 100);
//
// Add the facets to the mapwho and walkable faces to the mapwho.
//
build_quick_city();
// tum te tum
init_animals();
// what? function call? i din... oh, _that_ function call
//
// Process the prim data.
//
TRACE("Q1\n");
//
// We have to call DIRT_init() after we've loaded the map because
// it looks for trees to put clumps of leaves around.
//
DIRT_init(100, 1, 0, INFINITY, INFINITY, INFINITY, INFINITY);
//
// Map processing.
//
OB_convert_dustbins_to_barrels();
ROAD_sink();
ROAD_wander_calc();
WAND_init();
WARE_init();
MAV_precalculate();
extern void BUILD_car_facets();
BUILD_car_facets();
SHADOW_do();
// AZ_create_lines();
COLLIDE_calc_fastnav_bits();
COLLIDE_find_seethrough_fences();
clear_all_wmove_flags();
InitGrenades();
// now the map's loaded we can precalc audio polys, if req'd
#ifdef USE_A3D
SOUNDENV_precalc();
#endif
SOUND_SewerPrecalc();
//
// Load in the lighting.
//
if (fname_lighting == NULL || !NIGHT_load_ed_file(fname_lighting))
{
//
// Default lighting.
//
NIGHT_ambient(255, 255, 255, 110, -148, -177);
}
TRACE("Q2\n");
NIGHT_generate_walkable_lighting();
//
// Always rain at night.
//
if (!(NIGHT_flag & NIGHT_FLAG_DAYTIME))
{
GAME_FLAGS |= GF_RAINING;
}
ATTRACT_loadscreen_draw(60 * 256 / 100);
//
// Load the level.
//
ELEV_load_level(fname_level);
ATTRACT_loadscreen_draw(65 * 256 / 100);
#ifndef PSX
TEXTURE_fix_prim_textures();
// TEXTURE_fix_texture_styles();
AENG_create_dx_prim_points();
extern void envmap_specials(void);
envmap_specials();
#endif
calc_prim_info();
#ifndef PSX
calc_prim_normals();
find_anim_prim_bboxes();
#endif
loading_screen_active = TRUE;
if(!quick_load)
{
TEXTURE_load_needed(fname_level, 0, 256, 400);
extern void PACK_do(void);
// PACK_do();
}
loading_screen_active = FALSE;
EWAY_process(); //pre process map, stick it here Or we get stack overflow
// MUSIC_WORLD=(Random()%6)+1;
// MARK! THIS CODE ISN'T CALLED FOR THE DC!!!!
#if 0
extern void SND_BeginAmbient();
MFX_load_wave_list();
SND_BeginAmbient();
#else
ELEV_game_init_common ( fname_map, fname_lighting, fname_citsez, fname_level );
#endif
ATTRACT_loadscreen_draw(95 * 256 / 100);
//
// Load what the citizen's say.
//
EWAY_load_fake_wander_text(fname_citsez);
//
// Add the walkable faces in the objects to the mapwho. We do this after ELEV_load_level()
// because some of the objects are converted to moving platforms when we load a level.
//
OB_make_all_the_switches_be_at_the_proper_height();
OB_add_walkable_faces();
//
// Work out which edges of the walkable faces we can grab.
//
calc_slide_edges();
ATTRACT_loadscreen_draw(100 * 256 / 100);
//
// Set the camera to point at the player.
//
#ifdef OLD_CAM
CAM_set_focus(NET_PERSON(PLAYER_ID));
//CAM_set_mode (CAM_MODE_NORMAL);
//CAM_set_zoom (0x320);
//CAM_set_behind_up(0x38000);
//CAM_lens = CAM_LENS_WIDEANGLE;
CAM_set_type(CAM_TYPE_WIDE);
CAM_set_pos(
NET_PERSON(PLAYER_ID)->WorldPos.X + 0x10000 >> 8,
NET_PERSON(PLAYER_ID)->WorldPos.Y + 0x40000 >> 8,
NET_PERSON(PLAYER_ID)->WorldPos.Z + 0x10000 >> 8);
#endif
/*
HOOK_init(
NET_PERSON(PLAYER_ID)->WorldPos.X - 0x20000 >> 8,
NET_PERSON(PLAYER_ID)->WorldPos.Z - 0x20000 >> 8);
*/
//
// New camera.
//
if(CNET_network_game)
{
FC_look_at(0, THING_NUMBER(NET_PERSON(PLAYER_ID)));
}
else
{
for (i = 0; i < NO_PLAYERS; i++)
{
if (NET_PERSON(i))
{
FC_look_at(i, THING_NUMBER(NET_PERSON(i)));
FC_setup_initial_camera(i);
}
}
}
/*
{
Thing *darci = NET_PERSON(0);
darci_dlight = NIGHT_dlight_create(
(darci->WorldPos.X >> 8),
(darci->WorldPos.Y >> 8) + 0x80,
(darci->WorldPos.Z >> 8),
200,
30,
40,
50);
}
*/
// debug camera
/*
FC_look_at(1, 195);
FC_setup_initial_camera(1);
*/
// set boomboxes playing
/* for (i = 1; i < OB_ob_upto; i++)
{
if (OB_ob[i].prim==61)
MFX_play_xyz(0,S_TUNE_CLUB,MFX_LOOPED,OB_ob[i].x,OB_ob[i].y,OB_ob[i].z);
}*/
OB_Mapwho *om;
OB_Ob *oo;
SLONG num;
SLONG index;
SLONG j;
for (i=0;i<OB_SIZE-1;i++)
for (j=0;j<OB_SIZE-1;j++)
{
om = &OB_mapwho[i][j];
index = om->index;
num = om->num;
while(num--)
{
ASSERT(WITHIN(index, 1, OB_ob_upto - 1));
oo = &OB_ob[index];
if (oo->prim==61)
MFX_play_xyz(0,S_ACIEEED,MFX_LOOPED|MFX_OVERLAP,((i << 10) + (oo->x << 2))<<8, oo->y<<8, ((j << 10) + (oo->z << 2))<<8);
index++;
}
}
//
// Put puddles randomly around the city when its raining.
//
if (GAME_FLAGS & GF_RAINING)
{
PUDDLE_precalculate();
}
//
// Insert colvects on the edge of water and the edges of sewer
// entrances.
//
insert_collision_facets();
#if GET_RID_OF_THE_BLOODY_MIST
//
// Put down some mist.
//
MIST_create(
17,
84,
14914,
13655,
19010,
17751);
MIST_create(
17,
84,
8787,
4000,
12883,
8096);
#endif
TRACE("Q4\n");
//
// Clear all the keys!
//
Keys[KB_SPACE] = 0;
Keys[KB_ENTER] = 0;
Keys[KB_A] = 0;
Keys[KB_Z] = 0;
Keys[KB_X] = 0;
Keys[KB_C] = 0;
Keys[KB_V] = 0;
Keys[KB_LEFT] = 0;
Keys[KB_RIGHT] = 0;
Keys[KB_UP] = 0;
Keys[KB_DOWN] = 0;
ATTRACT_loadscreen_draw(100 * 256 / 100);
//save_dreamcast_wad(fname_level);
#if TEST_DC
extern UBYTE build_dc;
if (build_dc)
{
extern void PACK_do(void);
save_dreamcast_wad(fname_level);
#ifdef SAVE_MY_VQ_TEXTURES_PLEASE_BOB
//PACK_do();
#endif
}
else
{
save_dreamcast_wad(fname_level);
}
#endif // TEST_DC
return TRUE;
}
#endif
#endif
#ifndef PSX
//
// Fills the destination with the same filename (not the full path) of
// the source, except it has the given extension. (The extension does
// not include the '.')
//
void ELEV_create_similar_name(
CBYTE *dest,
CBYTE *src,
CBYTE *ext)
{
CBYTE *ch;
CBYTE *ci;
//
// Find the start of the source filename.
//
for (ch = src; *ch; ch++);
while(1)
{
if (ch == src)
{
break;
}
if (*ch == '\\')
{
ch++;
break;
}
ch--;
}
//
// Copy over the filename.
//
ci = dest;
while(1)
{
*ci++ = *ch++;
if (*ch == '.' || *ch == '\000')
{
break;
}
}
//
// Add the extension.
//
*ci++ = '.';
strcpy(ci, ext);
}
CBYTE ELEV_fname_map [_MAX_PATH];
CBYTE ELEV_fname_lighting[_MAX_PATH];
CBYTE ELEV_fname_citsez [_MAX_PATH];
CBYTE ELEV_fname_level [_MAX_PATH];
SLONG ELEV_load_name(CBYTE *fname_level)
{
SLONG ans;
CBYTE *fname_map;
CBYTE *fname_lighting;
CBYTE *fname_citsez;
MFFileHandle handle;
// Play FMV now, when we have enough memory to do so!
if (strstr(ELEV_fname_level, "Finale1.ucm"))
{
if (GAME_STATE & GS_REPLAY)
{
//
// Don't play cutscenes on replay.
//
}
else
{
stop_all_fx_and_music();
#ifdef TARGET_DC
the_display.RunCutscene( 2, ENV_get_value_number("lang_num", 0, "" ) );
#else
the_display.RunCutscene(2);
#endif
// Reshow the "loading" screen.
ATTRACT_loadscreen_init();
// And play the loading music, coz it's all in memory.
DCLL_memstream_play();
}
}
//
// Extract map, sewer and lighting filenames from the level file.
//
if (fname_level == NULL)
{
return FALSE;
}
handle = FileOpen(fname_level);
if (handle == FILE_OPEN_ERROR)
{
//
// Couldn't open file.
//
ASSERT ( FALSE );
return FALSE;
}
strcpy(ELEV_fname_level, fname_level); // I hope this is OK
//
// Load in the mission file.
//
char junk[1000];
if (FileRead(handle, junk, sizeof(SLONG)) == FILE_READ_ERROR) goto file_error; // Version number
if (FileRead(handle, junk, sizeof(SLONG)) == FILE_READ_ERROR) goto file_error; // Used
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // BriefName
if (FileRead(handle, ELEV_fname_lighting, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // LightMapName
if (FileRead(handle, ELEV_fname_map, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // MapName
if (FileRead(handle, junk, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // MissionName
if (FileRead(handle, ELEV_fname_citsez, _MAX_PATH) == FILE_READ_ERROR) goto file_error; // CitSezName
FileClose(handle);
//
// Sort out NULL filenames.
//
fname_map = (ELEV_fname_map [0]) ? ELEV_fname_map : NULL;
fname_lighting = (ELEV_fname_lighting[0]) ? ELEV_fname_lighting : NULL;
fname_citsez = (ELEV_fname_citsez [0]) ? ELEV_fname_citsez : NULL;
//
// Do the load.
//
#ifdef PSX
printf("Map Name:%s\nLighting:%s\nCitsez: %s\nLevel: %s\n",fname_map,fname_lighting,fname_citsez,fname_level);
#endif
ans = ELEV_game_init(
fname_map,
fname_lighting,
fname_citsez,
fname_level);
return ans;
file_error:;
FileClose(handle);
return TRUE;
}
extern MFFileHandle playback_file;
extern CBYTE tab_map_name[];
#endif
//extern SLONG EWAY_conv_active;
extern SLONG PSX_inv_open;
SLONG ELEV_load_user(SLONG mission)
{
#ifndef PSX
CBYTE *fname_map;
CBYTE *fname_lighting;
CBYTE *fname_citsez;
CBYTE *fname_level;
CBYTE curr_directory[_MAX_PATH];
#ifndef TARGET_DC
OPENFILENAME ofn;
#endif
MFX_QUICK_stop(TRUE);
MUSIC_mode(0);
MUSIC_mode_process();
#ifndef TARGET_DC
try_again:;
#endif
/*
if(mission<0)
{
//
// bodge for publishing meeting
//
{
SLONG c0;
strcpy(tab_map_name,my_mission_names[-mission]);
for(c0=0;c0<strlen(tab_map_name);c0++)
{
if(tab_map_name[c0]=='.')
{
tab_map_name[c0+1]='t';
tab_map_name[c0+2]='g';
tab_map_name[c0+3]='a';
break;
}
}
}
return ELEV_load_name(my_mission_names[-mission]);
}
*/
//
// Using the GetOpenFileName() function changes the current directory,
// so we must save and restore it.
//
#ifdef TARGET_DC
curr_directory[0] = '\0';
#else
GetCurrentDirectory(_MAX_PATH, curr_directory);
#endif
if(GAME_STATE&GS_PLAYBACK) {
UWORD c;
// marker to indicate level name is included
FileRead(playback_file,&c,2);
if (c==1) {
CBYTE temp[_MAX_PATH];
// restore string
FileRead(playback_file,&c,2);
FileRead(playback_file,temp,c);
strcpy(ELEV_fname_level,curr_directory);
if (ELEV_fname_level[strlen(ELEV_fname_level)-1]!='\\') strcat(ELEV_fname_level,"\\");
strcat(ELEV_fname_level,temp);
return ELEV_load_name(ELEV_fname_level);
/*
strcpy(ELEV_fname_level,temp);
return ELEV_load_name(&ELEV_fname_level[23]); // The stupid thing saves the absolute address
*/
}
}
#ifdef OBEY_SCRIPT
return ELEV_load_name(BRIEFING_mission_filename);
#endif
//extern CBYTE* STARTSCR_mission;
extern CBYTE STARTSCR_mission[_MAX_PATH];
if (*STARTSCR_mission)
{
//
// need to record level name for Restart
//
strcpy(ELEV_fname_level,STARTSCR_mission);
if(GAME_STATE&GS_RECORD)
{
UWORD c=1;
CBYTE fname[_MAX_PATH],*cname;
// marker to indicate level name is included
FileWrite(playback_file,&c,2);
// store string
strcpy(fname,ELEV_fname_level);
cname=fname;
if (strnicmp(fname,curr_directory,strlen(curr_directory))==0)
{
cname+=strlen(curr_directory);
if (*cname='\\') cname++;
}
c=strlen(cname)+1; // +1 is to include terminating zero
FileWrite(playback_file,&c,2);
FileWrite(playback_file,cname,c);
}
// MemFree(STARTSCR_mission);
SLONG res=ELEV_load_name(STARTSCR_mission);
*STARTSCR_mission=0;
return res;
}
#ifdef TARGET_DC
// Should never get here on DC.
ASSERT ( FALSE );
#else //#ifdef TARGET_DC
//
// So we can see the dialog boxes!
//
the_display.toGDI();
//
// Are we loading a combined level file or a bunch of separate files?
//
SLONG ans = MessageBox(
hDDLibWindow,
"Do you want to load a level file?",
"Load a (map + lighting + citsez) file or a single level file",
MB_YESNOCANCEL | MB_APPLMODAL | MB_ICONQUESTION);
switch(ans)
{
case IDYES:
//
// Get a level filename.
//
ELEV_fname_level[0] = 0;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDDLibWindow;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Level files\0*.ucm\0Wad files\0*.wad\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = ELEV_fname_level;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = "Levels";
ofn.lpstrTitle = "Load a level";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "ucm";
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (!GetOpenFileName(&ofn))
{
return FALSE;
}
//
// Restore our current directory.
//
SetCurrentDirectory(curr_directory);
if(GAME_STATE&GS_RECORD)
{
UWORD c=1;
CBYTE fname[_MAX_PATH],*cname;
// marker to indicate level name is included
FileWrite(playback_file,&c,2);
// store string
strcpy(fname,ELEV_fname_level);
cname=fname;
if (strnicmp(fname,curr_directory,strlen(curr_directory))==0)
{
cname+=strlen(curr_directory);
if (*cname='\\') cname++;
}
c=strlen(cname)+1; // +1 is to include terminating zero
FileWrite(playback_file,&c,2);
FileWrite(playback_file,cname,c);
}
/*
//
// Load the level.
//
{
SLONG c0;
strcpy(tab_map_name,ELEV_fname_level);
for(c0=0;c0<strlen(tab_map_name);c0++)
{
if(tab_map_name[c0]=='.')
{
tab_map_name[c0+1]='t';
tab_map_name[c0+2]='g';
tab_map_name[c0+3]='a';
break;
}
}
}
*/
if(ELEV_fname_level[strlen(ELEV_fname_level)-3]=='w')
{
//
// oh my god, crazy shit, it's a long shot but it just might work
//
extern void load_whole_game(CBYTE *gamename);
load_whole_game(ELEV_fname_level);
return(4);
}
else
{
if(ELEV_load_name(ELEV_fname_level))
return(5);
else
return(0);
}
return (ELEV_load_name(ELEV_fname_level)?5:0);
case IDNO:
//
// We have to get the map/lighting/and citsez files separately.
//
ELEV_fname_map[0] = 0;
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDDLibWindow;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Game map files\0*.iam\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = ELEV_fname_map;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = "data";
ofn.lpstrTitle = "Load a game map";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "iam";
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (!GetOpenFileName(&ofn))
{
goto try_again;
// return FALSE;
}
else
{
fname_map = ELEV_fname_map;
}
//
// Create the default lighting filename.
//
ELEV_create_similar_name(
ELEV_fname_lighting,
ELEV_fname_map,
"lgt");
//
// Restore our current directory.
//
SetCurrentDirectory(curr_directory);
//
// Get the lighting filename.
//
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDDLibWindow;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Lighting files\0*.lgt\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = ELEV_fname_lighting;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = "data\\lighting";
ofn.lpstrTitle = "Load a lighting file";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "lgt";
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (!GetOpenFileName(&ofn))
{
fname_lighting = NULL;
}
else
{
fname_lighting = ELEV_fname_lighting;
}
//
// Create the default citsez filename.
//
ELEV_create_similar_name(
ELEV_fname_citsez,
ELEV_fname_map,
"txt");
//
// Restore our current directory.
//
SetCurrentDirectory(curr_directory);
//
// Get the sewer filename.
//
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hDDLibWindow;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Text files\0*.txt\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = ELEV_fname_citsez;
ofn.nMaxFile = _MAX_PATH;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = "\\text";
ofn.lpstrTitle = "Load a Citizen-sez text file";
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "txt";
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (!GetOpenFileName(&ofn))
{
fname_citsez = NULL;
}
else
{
fname_citsez = ELEV_fname_citsez;
}
//
// We don't have a level.
//
fname_level = NULL;
//
// Restore our current directory.
//
SetCurrentDirectory(curr_directory);
//
// Do the load.
//
return ELEV_game_init(
fname_map,
fname_lighting,
fname_citsez,
fname_level);
case IDCANCEL:
return FALSE;
default:
return FALSE;
}
#endif //#else //#ifdef TARGET_DC
#else
#if 1
extern void load_whole_game(CBYTE *gamename);
extern char *Wadmenu_AttractMenu(void);
extern UBYTE Wadmenu_Video;
extern int Wadmenu_Levelwon;
extern UBYTE Eidos_Played;
extern void Wadmenu_Introduction();
#ifndef VERSION_DEMO
do
{
#endif
// Stop all sound effects playing
MFX_OffKey=-1;
MFX_render();
DrawSync(0);
PSXOverLay(OVERLAY_NAME,OVERLAY_SIZE);
if (!Eidos_Played)
{
Wadmenu_Introduction();
}
if ((wad_level==33)&&Wadmenu_Levelwon)
Wadmenu_Video=4;
psx_game_name=Wadmenu_AttractMenu();
// psx_game_name="levels\\level07\\level.nad";
if (strcmp(psx_game_name,"MDEC")==0)
psx_game_name=NULL;
#ifndef VERSION_DEMO
}
while(!psx_game_name);
#else
if (psx_game_name==NULL)
return 0;
#endif
load_whole_game(psx_game_name);
// load_whole_game("levels\\botanic1.wad");
DIRT_init(100, 1, 0, INFINITY, INFINITY, INFINITY, INFINITY);
InitGrenades();
SPARK_init();
extern void PANEL_new_text_init();
extern void PANEL_new_widescreen_init();
PANEL_new_text_init();
PANEL_new_widescreen_init();
MUSIC_init_level(wad_level);
MFX_Init_Speech(wad_level);
PSX_eog_timer=60;
EWAY_conv_active=0;
PSX_inv_open=0;
extern void init_record(SLONG level);
#ifndef FS_ISO9660
init_record(wad_level);
#endif
return(4);
// return ELEV_load_name("levels\\psx_test.ucp");
#else
CBYTE *fname_map="data\\jumper1.iam";
CBYTE *fname_lighting="data\\lighting\\jumper1.lgt";
CBYTE *fname_citsez=NULL;//"data\\gptest1.sew";
CBYTE *fname_level=NULL; //"data\\gptest1.ucm";
return ELEV_game_init(
fname_map,
fname_lighting,
fname_citsez,
fname_level);
#endif
#endif
}
void reload_level(void)
{
#ifndef PSX
ELEV_load_name(ELEV_fname_level);
#else
extern void load_whole_game(CBYTE *gamename);
extern void Wadmenu_LoadingScreen(TIM_IMAGE *tim);
extern void *mem_all;
extern void setup_textures(int world);
TIM_IMAGE tim;
extern void end_record(void);
#ifndef FS_ISO9660
end_record();
#endif
SetupMemory();
mem_all=0;
MFX_OffKey=-1;
MFX_render();
ClearOTag(the_display.CurrentDisplayBuffer->ot,OTSIZE);
PSXOverLay(OVERLAY_NAME,OVERLAY_SIZE);
// setup_textures(0);
Wadmenu_LoadingScreen(&tim);
load_whole_game(psx_game_name);
DIRT_init(100, 1, 0, INFINITY, INFINITY, INFINITY, INFINITY);
InitGrenades();
SPARK_init();
extern void PANEL_new_text_init();
extern void PANEL_new_widescreen_init();
MUSIC_init_level(wad_level);
MFX_Init_Speech(wad_level);
PANEL_new_text_init();
PANEL_new_widescreen_init();
PSX_eog_timer=60;
EWAY_conv_active=0;
PSX_inv_open=0;
extern void init_playback(void);
// init_playback();
#endif
}