2006-03-20 16:43:15 +00:00
/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
2010-06-14 08:13:16 +00:00
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
2006-03-20 16:43:15 +00:00
COPYRIGHT 1993 - 1998 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
2008-04-06 20:23:28 +00:00
2006-03-20 16:43:15 +00:00
/*
*
2007-07-18 21:36:53 +00:00
* Routines for EndGame , EndLevel , etc .
2006-03-20 16:43:15 +00:00
*
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <errno.h>
# include <time.h>
# ifdef OGL
# include "ogl_init.h"
# endif
# include "inferno.h"
# include "game.h"
# include "key.h"
# include "object.h"
# include "physics.h"
# include "error.h"
# include "joy.h"
# include "iff.h"
# include "pcx.h"
# include "timer.h"
# include "render.h"
# include "laser.h"
# include "screens.h"
# include "textures.h"
# include "slew.h"
# include "gauges.h"
# include "texmap.h"
# include "3d.h"
# include "effects.h"
# include "menu.h"
# include "gameseg.h"
# include "wall.h"
# include "ai.h"
# include "hostage.h"
# include "fuelcen.h"
# include "switch.h"
# include "digi.h"
# include "gamesave.h"
# include "scores.h"
# include "u_mem.h"
# include "palette.h"
# include "morph.h"
# include "lighting.h"
# include "newdemo.h"
# include "titles.h"
# include "collide.h"
# include "weapon.h"
# include "sounds.h"
# include "args.h"
# include "gameseq.h"
# include "gamefont.h"
# include "newmenu.h"
# include "endlevel.h"
# include "playsave.h"
# include "ctype.h"
# include "multi.h"
# include "fireball.h"
# include "kconfig.h"
# include "config.h"
# include "robot.h"
# include "automap.h"
# include "cntrlcen.h"
# include "powerup.h"
# include "text.h"
# include "piggy.h"
# include "texmerge.h"
# include "paging.h"
# include "mission.h"
# include "state.h"
# include "songs.h"
2008-04-24 14:27:54 +00:00
# ifdef NETWORK
2009-03-20 12:10:38 +00:00
# include "multi.h"
2008-04-24 14:27:54 +00:00
# endif
2006-03-20 16:43:15 +00:00
# include "strutil.h"
# ifdef EDITOR
# include "editor/editor.h"
# endif
# include "custom.h"
# ifdef SCRIPT
# include "script.h"
# endif
2011-05-22 17:54:44 +00:00
# include "byteswap.h"
# include "segment.h"
# include "gameseg.h"
2006-03-20 16:43:15 +00:00
2012-04-15 13:32:46 +00:00
void init_player_stats_new_ship ( ubyte pnum ) ;
2006-03-20 16:43:15 +00:00
void copy_defaults_to_robot_all ( void ) ;
int AdvanceLevel ( int secret_flag ) ;
void StartLevel ( int random ) ;
//Current_level_num starts at 1 for the first level
//-1,-2,-3 are secret levels
//0 means not a real level loaded
int Current_level_num = 0 , Next_level_num ;
2010-06-14 08:13:16 +00:00
char Current_level_name [ LEVEL_NAME_LEN ] ;
2006-03-20 16:43:15 +00:00
2008-01-23 17:25:09 +00:00
// #ifndef SHAREWARE
// int Last_level,Last_secret_level;
// #endif
2006-03-20 16:43:15 +00:00
// Global variables describing the player
int N_players = 1 ; // Number of players ( >1 means a net game, eh?)
int Player_num = 0 ; // The player number who is on the console.
player Players [ MAX_PLAYERS ] ; // Misc player info
obj_position Player_init [ MAX_PLAYERS ] ;
// Global variables telling what sort of game we have
int NumNetPlayerPositions = - 1 ;
2011-01-14 16:56:14 +00:00
extern fix ThisLevelTime ;
2006-03-20 16:43:15 +00:00
// Extern from game.c to fix a bug in the cockpit!
extern int last_drawn_cockpit ;
extern int Last_level_path_created ;
void HUD_clear_messages ( ) ; // From hud.c
void verify_console_object ( )
{
Assert ( Player_num > - 1 ) ;
Assert ( Players [ Player_num ] . objnum > - 1 ) ;
ConsoleObject = & Objects [ Players [ Player_num ] . objnum ] ;
Assert ( ConsoleObject - > id = = Player_num ) ;
}
2010-06-14 08:13:16 +00:00
int count_number_of_robots ( )
2006-03-20 16:43:15 +00:00
{
int robot_count ;
int i ;
robot_count = 0 ;
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( Objects [ i ] . type = = OBJ_ROBOT )
robot_count + + ;
}
return robot_count ;
}
2010-06-14 08:13:16 +00:00
int count_number_of_hostages ( )
2006-03-20 16:43:15 +00:00
{
int count ;
int i ;
count = 0 ;
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( Objects [ i ] . type = = OBJ_HOSTAGE )
count + + ;
}
return count ;
}
void
gameseq_init_network_players ( )
{
int i , k , j ;
// Initialize network player start locations and object numbers
ConsoleObject = & Objects [ 0 ] ;
k = 0 ;
j = 0 ;
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( ( Objects [ i ] . type = = OBJ_PLAYER ) | | ( Objects [ i ] . type = = OBJ_GHOST ) | | ( Objects [ i ] . type = = OBJ_COOP ) )
{
# ifndef SHAREWARE
if ( ( ! ( Game_mode & GM_MULTI_COOP ) & & ( ( Objects [ i ] . type = = OBJ_PLAYER ) | | ( Objects [ i ] . type = = OBJ_GHOST ) ) ) | |
( ( Game_mode & GM_MULTI_COOP ) & & ( ( j = = 0 ) | | ( Objects [ i ] . type = = OBJ_COOP ) ) ) )
{
Objects [ i ] . type = OBJ_PLAYER ;
# endif
Player_init [ k ] . pos = Objects [ i ] . pos ;
Player_init [ k ] . orient = Objects [ i ] . orient ;
Player_init [ k ] . segnum = Objects [ i ] . segnum ;
Players [ k ] . objnum = i ;
Objects [ i ] . id = k ;
k + + ;
# ifndef SHAREWARE
}
else
obj_delete ( i ) ;
j + + ;
# endif
}
}
NumNetPlayerPositions = k ;
}
void gameseq_remove_unused_players ( )
{
int i ;
// 'Remove' the unused players
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
{
for ( i = 0 ; i < NumNetPlayerPositions ; i + + )
{
if ( ( ! Players [ i ] . connected ) | | ( i > = N_players ) )
{
multi_make_player_ghost ( i ) ;
}
}
}
else
# endif
{ // Note link to above if!!!
for ( i = 1 ; i < NumNetPlayerPositions ; i + + )
{
obj_delete ( Players [ i ] . objnum ) ;
}
}
}
// Setup player for new game
2012-04-15 13:32:46 +00:00
void init_player_stats_game ( ubyte pnum )
2006-03-20 16:43:15 +00:00
{
2012-04-15 13:32:46 +00:00
Players [ pnum ] . score = 0 ;
Players [ pnum ] . last_score = 0 ;
Players [ pnum ] . lives = INITIAL_LIVES ;
Players [ pnum ] . level = 1 ;
Players [ pnum ] . time_level = 0 ;
Players [ pnum ] . time_total = 0 ;
Players [ pnum ] . hours_level = 0 ;
Players [ pnum ] . hours_total = 0 ;
Players [ pnum ] . killer_objnum = - 1 ;
Players [ pnum ] . net_killed_total = 0 ;
Players [ pnum ] . net_kills_total = 0 ;
Players [ pnum ] . num_kills_level = 0 ;
Players [ pnum ] . num_kills_total = 0 ;
Players [ pnum ] . num_robots_level = 0 ;
Players [ pnum ] . num_robots_total = 0 ;
Players [ pnum ] . KillGoalCount = 0 ;
Players [ pnum ] . hostages_rescued_total = 0 ;
Players [ pnum ] . hostages_level = 0 ;
Players [ pnum ] . hostages_total = 0 ;
Players [ pnum ] . laser_level = 0 ;
Players [ pnum ] . flags = 0 ;
init_player_stats_new_ship ( pnum ) ;
2006-03-20 16:43:15 +00:00
}
void init_ammo_and_energy ( void )
{
if ( Players [ Player_num ] . energy < MAX_ENERGY )
Players [ Player_num ] . energy = MAX_ENERGY ;
if ( Players [ Player_num ] . shields < MAX_SHIELDS )
Players [ Player_num ] . shields = MAX_SHIELDS ;
// for (i=0; i<MAX_PRIMARY_WEAPONS; i++)
// if (Players[Player_num].primary_ammo[i] < Default_primary_ammo_level[i])
// Players[Player_num].primary_ammo[i] = Default_primary_ammo_level[i];
// for (i=0; i<MAX_SECONDARY_WEAPONS; i++)
// if (Players[Player_num].secondary_ammo[i] < Default_secondary_ammo_level[i])
// Players[Player_num].secondary_ammo[i] = Default_secondary_ammo_level[i];
if ( Players [ Player_num ] . secondary_ammo [ 0 ] < 2 + NDL - Difficulty_level )
Players [ Player_num ] . secondary_ammo [ 0 ] = 2 + NDL - Difficulty_level ;
}
// Setup player for new level (After completion of previous level)
void init_player_stats_level ( )
{
// int i;
Players [ Player_num ] . last_score = Players [ Player_num ] . score ;
Players [ Player_num ] . level = Current_level_num ;
# ifdef NETWORK
if ( ! Network_rejoined )
# endif
Players [ Player_num ] . time_level = 0 ; //Note link to above if !!!!!!
init_ammo_and_energy ( ) ;
Players [ Player_num ] . killer_objnum = - 1 ;
Players [ Player_num ] . num_kills_level = 0 ;
Players [ Player_num ] . num_robots_level = count_number_of_robots ( ) ;
Players [ Player_num ] . num_robots_total + = Players [ Player_num ] . num_robots_level ;
Players [ Player_num ] . hostages_level = count_number_of_hostages ( ) ;
Players [ Player_num ] . hostages_total + = Players [ Player_num ] . hostages_level ;
Players [ Player_num ] . hostages_on_board = 0 ;
Players [ Player_num ] . flags & = ( ~ KEY_BLUE ) ;
Players [ Player_num ] . flags & = ( ~ KEY_RED ) ;
Players [ Player_num ] . flags & = ( ~ KEY_GOLD ) ;
Players [ Player_num ] . flags & = ( ~ PLAYER_FLAGS_INVULNERABLE ) ;
Players [ Player_num ] . flags & = ( ~ PLAYER_FLAGS_CLOAKED ) ;
Players [ Player_num ] . cloak_time = 0 ;
Players [ Player_num ] . invulnerable_time = 0 ;
if ( ( Game_mode & GM_MULTI ) & & ! ( Game_mode & GM_MULTI_COOP ) )
Players [ Player_num ] . flags | = ( KEY_BLUE | KEY_RED | KEY_GOLD ) ;
Player_is_dead = 0 ; // Added by RH
2011-01-18 19:02:02 +00:00
Dead_player_camera = NULL ;
2006-03-20 16:43:15 +00:00
Players [ Player_num ] . homing_object_dist = - F1_0 ; // Added by RH
2010-09-03 21:49:39 +00:00
// properly init these cursed globals
2010-12-22 00:17:49 +00:00
Next_flare_fire_time = Last_laser_fired_time = Next_laser_fire_time = Next_missile_fire_time = GameTime64 ;
2006-03-20 16:43:15 +00:00
init_gauges ( ) ;
}
// Setup player for a brand-new ship
2012-04-15 13:32:46 +00:00
void init_player_stats_new_ship ( ubyte pnum )
2006-03-20 16:43:15 +00:00
{
2012-04-15 13:32:46 +00:00
int i ;
2006-03-20 16:43:15 +00:00
2012-04-15 13:32:46 +00:00
if ( pnum = = Player_num )
{
if ( Newdemo_state = = ND_STATE_RECORDING )
{
newdemo_record_laser_level ( Players [ Player_num ] . laser_level , 0 ) ;
newdemo_record_player_weapon ( 0 , 0 ) ;
newdemo_record_player_weapon ( 1 , 0 ) ;
}
Global_laser_firing_count = 0 ;
Primary_weapon = 0 ;
Secondary_weapon = 0 ;
dead_player_end ( ) ; //player no longer dead
2012-04-15 23:13:27 +00:00
Player_is_dead = 0 ;
Player_exploded = 0 ;
Player_eggs_dropped = 0 ;
Dead_player_camera = 0 ;
2006-03-20 16:43:15 +00:00
}
2012-04-15 13:32:46 +00:00
Players [ pnum ] . energy = MAX_ENERGY ;
Players [ pnum ] . shields = MAX_SHIELDS ;
Players [ pnum ] . laser_level = 0 ;
Players [ pnum ] . killer_objnum = - 1 ;
Players [ pnum ] . hostages_on_board = 0 ;
2006-03-20 16:43:15 +00:00
for ( i = 0 ; i < MAX_PRIMARY_WEAPONS ; i + + )
2012-04-15 13:32:46 +00:00
Players [ pnum ] . primary_ammo [ i ] = 0 ;
2006-03-20 16:43:15 +00:00
for ( i = 1 ; i < MAX_SECONDARY_WEAPONS ; i + + )
2012-04-15 13:32:46 +00:00
Players [ pnum ] . secondary_ammo [ i ] = 0 ;
Players [ pnum ] . secondary_ammo [ 0 ] = 2 + NDL - Difficulty_level ;
Players [ pnum ] . primary_weapon_flags = HAS_LASER_FLAG ;
Players [ pnum ] . secondary_weapon_flags = HAS_CONCUSSION_FLAG ;
Players [ pnum ] . flags & = ~ ( PLAYER_FLAGS_QUAD_LASERS | PLAYER_FLAGS_AFTERBURNER | PLAYER_FLAGS_CLOAKED | PLAYER_FLAGS_INVULNERABLE ) ;
Players [ pnum ] . cloak_time = 0 ;
Players [ pnum ] . invulnerable_time = 0 ;
Players [ pnum ] . homing_object_dist = - F1_0 ;
digi_kill_sound_linked_to_object ( Players [ pnum ] . objnum ) ;
2006-03-20 16:43:15 +00:00
}
# ifdef NETWORK
void reset_network_objects ( )
{
memset ( local_to_remote , - 1 , MAX_OBJECTS * sizeof ( short ) ) ;
2012-04-15 13:32:46 +00:00
memset ( remote_to_local , - 1 , MAX_PLAYERS * MAX_OBJECTS * sizeof ( short ) ) ;
2006-03-20 16:43:15 +00:00
memset ( object_owner , - 1 , MAX_OBJECTS ) ;
}
# endif
# ifdef EDITOR
2012-03-19 05:48:35 +00:00
extern int game_handler ( window * wind , d_event * event , void * data ) ;
2006-03-20 16:43:15 +00:00
//reset stuff so game is semi-normal when playing from editor
void editor_reset_stuff_on_level ( )
{
gameseq_init_network_players ( ) ;
init_player_stats_level ( ) ;
Viewer = ConsoleObject ;
ConsoleObject = Viewer = & Objects [ Players [ Player_num ] . objnum ] ;
ConsoleObject - > id = Player_num ;
ConsoleObject - > control_type = CT_FLYING ;
ConsoleObject - > movement_type = MT_PHYSICS ;
Game_suspended = 0 ;
verify_console_object ( ) ;
2009-07-01 11:35:33 +00:00
Control_center_destroyed = 0 ;
2006-03-20 16:43:15 +00:00
if ( Newdemo_state ! = ND_STATE_PLAYBACK )
gameseq_remove_unused_players ( ) ;
init_cockpit ( ) ;
init_robots_for_level ( ) ;
init_ai_objects ( ) ;
init_morphs ( ) ;
init_all_matcens ( ) ;
2012-04-15 13:32:46 +00:00
init_player_stats_new_ship ( Player_num ) ;
2012-03-19 05:48:35 +00:00
if ( ! Game_wind )
Game_wind = window_create ( & grd_curscreen - > sc_canvas , 0 , 0 , SWIDTH , SHEIGHT , game_handler , NULL ) ;
2006-03-20 16:43:15 +00:00
}
# endif
void reset_player_object ( ) ;
//do whatever needs to be done when a player dies in multiplayer
void DoGameOver ( )
{
# ifndef SHAREWARE
2008-01-23 17:25:09 +00:00
if ( PLAYING_BUILTIN_MISSION )
2006-03-20 16:43:15 +00:00
# endif
scores_maybe_add_player ( 0 ) ;
2010-01-27 04:30:31 +00:00
if ( Game_wind )
window_close ( Game_wind ) ; // Exit out of game loop
2006-03-20 16:43:15 +00:00
}
//update various information about the player
void update_player_stats ( )
{
// I took out this 'if' because it was causing the reactor invul time to be
// off for players that sit in the death screen. -JS jul 6,95
// if (!Player_exploded) {
Players [ Player_num ] . time_level + = FrameTime ; //the never-ending march of time...
if ( Players [ Player_num ] . time_level > i2f ( 3600 ) ) {
Players [ Player_num ] . time_level - = i2f ( 3600 ) ;
Players [ Player_num ] . hours_level + + ;
}
Players [ Player_num ] . time_total + = FrameTime ; //the never-ending march of time...
if ( Players [ Player_num ] . time_total > i2f ( 3600 ) ) {
Players [ Player_num ] . time_total - = i2f ( 3600 ) ;
Players [ Player_num ] . hours_total + + ;
}
// }
// Players[Player_num].energy += FrameTime*Energy_regen_ratio; //slowly regenerate energy
//MK1015: //slowly reduces player's energy & shields if over max
//MK1015:
//MK1015: if (Players[Player_num].energy > MAX_ENERGY) {
//MK1015: Players[Player_num].energy -= FrameTime/8;
//MK1015: if (Players[Player_num].energy < MAX_ENERGY)
//MK1015: Players[Player_num].energy = MAX_ENERGY;
//MK1015: }
//MK1015:
//MK1015: if (Players[Player_num].shields > MAX_SHIELDS) {
//MK1015: Players[Player_num].shields -= FrameTime/8;
//MK1015: if (Players[Player_num].shields < MAX_SHIELDS)
//MK1015: Players[Player_num].shields = MAX_SHIELDS;
//MK1015: }
}
//go through this level and start any eclip sounds
void set_sound_sources ( )
{
int segnum , sidenum ;
segment * seg ;
digi_init_sounds ( ) ; //clear old sounds
for ( seg = & Segments [ 0 ] , segnum = 0 ; segnum < = Highest_segment_index ; seg + + , segnum + + )
for ( sidenum = 0 ; sidenum < MAX_SIDES_PER_SEGMENT ; sidenum + + ) {
int tm , ec , sn ;
if ( ( tm = seg - > sides [ sidenum ] . tmap_num2 ) ! = 0 )
if ( ( ec = TmapInfo [ tm & 0x3fff ] . eclip_num ) ! = - 1 )
if ( ( sn = Effects [ ec ] . sound_num ) ! = - 1 ) {
vms_vector pnt ;
compute_center_point_on_side ( & pnt , seg , sidenum ) ;
digi_link_sound_to_pos ( sn , segnum , sidenum , & pnt , 1 , F1_0 / 2 ) ;
}
}
}
//fix flash_dist=i2f(1);
fix flash_dist = fl2f ( .9 ) ;
//create flash for player appearance
void create_player_appearance_effect ( object * player_obj )
{
vms_vector pos ;
object * effect_obj ;
# ifndef NDEBUG
{
int objnum = player_obj - Objects ;
if ( ( objnum < 0 ) | | ( objnum > Highest_object_index ) )
Int3 ( ) ; // See Rob, trying to track down weird network bug
}
# endif
if ( player_obj = = Viewer )
vm_vec_scale_add ( & pos , & player_obj - > pos , & player_obj - > orient . fvec , fixmul ( player_obj - > size , flash_dist ) ) ;
else
pos = player_obj - > pos ;
effect_obj = object_create_explosion ( player_obj - > segnum , & pos , player_obj - > size , VCLIP_PLAYER_APPEARANCE ) ;
if ( effect_obj ) {
effect_obj - > orient = player_obj - > orient ;
if ( Vclip [ VCLIP_PLAYER_APPEARANCE ] . sound_num > - 1 )
digi_link_sound_to_object ( Vclip [ VCLIP_PLAYER_APPEARANCE ] . sound_num , effect_obj - Objects , 0 , F1_0 ) ;
}
}
//
// New Game sequencing functions
//
extern int descent_critical_error ;
//get level filename. level numbers start at 1. Secret levels are -1,-2,-3
char * get_level_file ( int level_num )
{
# ifdef SHAREWARE
{
static char t [ 13 ] ;
sprintf ( t , " level%02d.sdl " , level_num ) ;
return t ;
}
# else
if ( level_num < 0 ) //secret level
return Secret_level_names [ - level_num - 1 ] ;
else //normal level
return Level_names [ level_num - 1 ] ;
# endif
}
2011-05-22 17:54:44 +00:00
// routine to calculate the checksum of the segments.
void do_checksum_calc ( ubyte * b , int len , unsigned int * s1 , unsigned int * s2 )
2009-03-20 12:10:38 +00:00
{
while ( len - - ) {
* s1 + = * b + + ;
if ( * s1 > = 255 ) * s1 - = 255 ;
* s2 + = * s1 ;
}
}
2011-05-22 17:54:44 +00:00
ushort netmisc_calc_checksum ( )
2009-03-20 12:10:38 +00:00
{
int i , j , k ;
unsigned int sum1 , sum2 ;
short s ;
int t ;
sum1 = sum2 = 0 ;
for ( i = 0 ; i < Highest_segment_index + 1 ; i + + ) {
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + ) {
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( unsigned char * ) & ( Segments [ i ] . sides [ j ] . type ) , 1 , & sum1 , & sum2 ) ;
do_checksum_calc ( & ( Segments [ i ] . sides [ j ] . pad ) , 1 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
s = INTEL_SHORT ( Segments [ i ] . sides [ j ] . wall_num ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
s = INTEL_SHORT ( Segments [ i ] . sides [ j ] . tmap_num ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
s = INTEL_SHORT ( Segments [ i ] . sides [ j ] . tmap_num2 ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
for ( k = 0 ; k < 4 ; k + + ) {
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . uvls [ k ] . u ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . uvls [ k ] . v ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . uvls [ k ] . l ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
}
for ( k = 0 ; k < 2 ; k + + ) {
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . normals [ k ] . x ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . normals [ k ] . y ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
t = INTEL_INT ( ( ( int ) Segments [ i ] . sides [ j ] . normals [ k ] . z ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
}
}
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + ) {
s = INTEL_SHORT ( Segments [ i ] . children [ j ] ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
}
for ( j = 0 ; j < MAX_VERTICES_PER_SEGMENT ; j + + ) {
s = INTEL_SHORT ( Segments [ i ] . verts [ j ] ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
}
s = INTEL_SHORT ( Segments [ i ] . objects ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
do_checksum_calc ( ( unsigned char * ) & ( Segments [ i ] . special ) , 1 , & sum1 , & sum2 ) ;
do_checksum_calc ( ( unsigned char * ) & ( Segments [ i ] . matcen_num ) , 1 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
s = INTEL_SHORT ( Segments [ i ] . value ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
t = INTEL_INT ( ( ( int ) Segments [ i ] . static_light ) ) ;
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & t , 4 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
# ifndef EDITOR
s = INTEL_SHORT ( Segments [ i ] . pad ) ; // necessary? If this isn't set to 0 it won't work Intel-Intel anyway.
2011-05-22 17:54:44 +00:00
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
# else
s = INTEL_SHORT ( 0 ) ; // no matter if we need alignment on our platform, if we have editor we MUST consider this integer to get the same checksum as non-editor games calculate
do_checksum_calc ( ( ubyte * ) & s , 2 , & sum1 , & sum2 ) ;
2009-03-20 12:10:38 +00:00
# endif
}
sum2 % = 255 ;
return ( ( sum1 < < 8 ) + sum2 ) ;
}
2006-03-20 16:43:15 +00:00
//load a level off disk. level numbers start at 1. Secret levels are -1,-2,-3
2010-06-14 08:13:16 +00:00
void LoadLevel ( int level_num )
2006-03-20 16:43:15 +00:00
{
char * level_name ;
player save_player ;
2010-06-14 08:13:16 +00:00
save_player = Players [ Player_num ] ;
2006-03-20 16:43:15 +00:00
Assert ( level_num < = Last_level & & level_num > = Last_secret_level & & level_num ! = 0 ) ;
level_name = get_level_file ( level_num ) ;
if ( ! load_level ( level_name ) )
Current_level_num = level_num ;
2007-08-08 12:38:13 +00:00
gr_use_palette_table ( " palette.256 " ) ;
2008-03-20 23:23:46 +00:00
show_boxed_message ( TXT_LOADING , 0 ) ;
2010-06-27 11:28:26 +00:00
# ifdef RELEASE
timer_delay ( F1_0 ) ;
# endif
2008-03-20 23:23:46 +00:00
2006-03-20 16:43:15 +00:00
# ifdef NETWORK
2011-05-22 17:54:44 +00:00
my_segments_checksum = netmisc_calc_checksum ( ) ;
2006-03-20 16:43:15 +00:00
# endif
load_endlevel_data ( level_num ) ;
2010-10-16 09:13:11 +00:00
load_custom_data ( level_name ) ;
2006-03-20 16:43:15 +00:00
# ifdef NETWORK
reset_network_objects ( ) ;
# endif
Players [ Player_num ] = save_player ;
set_sound_sources ( ) ;
2010-08-01 17:42:38 +00:00
songs_play_level_song ( Current_level_num , 0 ) ;
2006-03-20 16:43:15 +00:00
2010-03-27 10:31:34 +00:00
gr_palette_load ( gr_palette ) ; //actually load the palette
2006-03-20 16:43:15 +00:00
}
//sets up Player_num & ConsoleObject
void InitPlayerObject ( )
{
Assert ( Player_num > = 0 & & Player_num < MAX_PLAYERS ) ;
if ( Player_num ! = 0 ) {
Players [ 0 ] = Players [ Player_num ] ;
Player_num = 0 ;
}
Players [ Player_num ] . objnum = 0 ;
ConsoleObject = & Objects [ Players [ Player_num ] . objnum ] ;
ConsoleObject - > type = OBJ_PLAYER ;
ConsoleObject - > id = Player_num ;
ConsoleObject - > control_type = CT_FLYING ;
ConsoleObject - > movement_type = MT_PHYSICS ;
}
//starts a new game on the given level
void StartNewGame ( int start_level )
{
2010-07-19 17:07:12 +00:00
state_quick_item = - 1 ; // for first blind save, pick slot to save in
2010-02-25 03:08:10 +00:00
2006-03-20 16:43:15 +00:00
Game_mode = GM_NORMAL ;
Next_level_num = 0 ;
InitPlayerObject ( ) ; //make sure player's object set up
2012-04-15 13:32:46 +00:00
init_player_stats_game ( Player_num ) ; //clear all stats
2006-03-20 16:43:15 +00:00
N_players = 1 ;
# ifdef SCRIPT
script_reset ( ) ;
script_load ( " default.scr " ) ;
# endif
StartNewLevel ( start_level ) ;
Players [ Player_num ] . starting_level = start_level ; // Mark where they started
game_disable_cheats ( ) ;
}
// -----------------------------------------------------------------------------
// Does the bonus scoring.
// Call with dead_flag = 1 if player died, but deserves some portion of bonus (only skill points), anyway.
void DoEndLevelScoreGlitz ( int network )
2010-06-14 08:13:16 +00:00
{
2006-03-20 16:43:15 +00:00
int level_points , skill_points , energy_points , shield_points , hostage_points ;
int all_hostage_points ;
int endgame_points ;
char all_hostage_text [ 64 ] ;
char endgame_text [ 64 ] ;
# define N_GLITZITEMS 9
char m_str [ N_GLITZITEMS ] [ 30 ] ;
newmenu_item m [ 9 ] ;
int i , c ;
char title [ 128 ] ;
int is_last_level ;
2008-03-20 23:23:46 +00:00
gr_palette_load ( gr_palette ) ;
2006-03-20 16:43:15 +00:00
level_points = Players [ Player_num ] . score - Players [ Player_num ] . last_score ;
2011-02-14 21:27:02 +00:00
if ( ! cheats . enabled ) {
2006-03-20 16:43:15 +00:00
if ( Difficulty_level > 1 ) {
skill_points = level_points * ( Difficulty_level - 1 ) / 2 ;
skill_points - = skill_points % 100 ;
} else
skill_points = 0 ;
shield_points = f2i ( Players [ Player_num ] . shields ) * 10 * ( Difficulty_level + 1 ) ;
energy_points = f2i ( Players [ Player_num ] . energy ) * 5 * ( Difficulty_level + 1 ) ;
hostage_points = Players [ Player_num ] . hostages_on_board * 500 * ( Difficulty_level + 1 ) ;
} else {
skill_points = 0 ;
shield_points = 0 ;
energy_points = 0 ;
hostage_points = 0 ;
}
all_hostage_text [ 0 ] = 0 ;
endgame_text [ 0 ] = 0 ;
2011-02-14 21:27:02 +00:00
if ( ! cheats . enabled & & ( Players [ Player_num ] . hostages_on_board = = Players [ Player_num ] . hostages_level ) ) {
2006-03-20 16:43:15 +00:00
all_hostage_points = Players [ Player_num ] . hostages_on_board * 1000 * ( Difficulty_level + 1 ) ;
sprintf ( all_hostage_text , " %s%i \n " , TXT_FULL_RESCUE_BONUS , all_hostage_points ) ;
} else
all_hostage_points = 0 ;
2011-02-14 21:27:02 +00:00
if ( ! cheats . enabled & & ! ( Game_mode & GM_MULTI ) & & ( Players [ Player_num ] . lives ) & & ( Current_level_num = = Last_level ) ) { //player has finished the game!
2006-03-20 16:43:15 +00:00
endgame_points = Players [ Player_num ] . lives * 10000 ;
sprintf ( endgame_text , " %s%i \n " , TXT_SHIP_BONUS , endgame_points ) ;
is_last_level = 1 ;
} else
endgame_points = is_last_level = 0 ;
add_bonus_points_to_score ( skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points ) ;
c = 0 ;
sprintf ( m_str [ c + + ] , " %s%i " , TXT_SHIELD_BONUS , shield_points ) ; // Return at start to lower menu...
sprintf ( m_str [ c + + ] , " %s%i " , TXT_ENERGY_BONUS , energy_points ) ;
sprintf ( m_str [ c + + ] , " %s%i " , TXT_HOSTAGE_BONUS , hostage_points ) ;
sprintf ( m_str [ c + + ] , " %s%i " , TXT_SKILL_BONUS , skill_points ) ;
sprintf ( m_str [ c + + ] , " %s " , all_hostage_text ) ;
if ( ! ( Game_mode & GM_MULTI ) & & ( Players [ Player_num ] . lives ) & & ( Current_level_num = = Last_level ) )
sprintf ( m_str [ c + + ] , " %s " , endgame_text ) ;
sprintf ( m_str [ c + + ] , " %s%i \n " , TXT_TOTAL_BONUS , shield_points + energy_points + hostage_points + skill_points + all_hostage_points + endgame_points ) ;
sprintf ( m_str [ c + + ] , " %s%i " , TXT_TOTAL_SCORE , Players [ Player_num ] . score ) ;
for ( i = 0 ; i < c ; i + + ) {
m [ i ] . type = NM_TYPE_TEXT ;
m [ i ] . text = m_str [ i ] ;
}
// m[c].type = NM_TYPE_MENU; m[c++].text = "Ok";
if ( Current_level_num < 0 )
sprintf ( title , " %s%s %d %s \n %s %s " , is_last_level ? " \n \n \n " : " \n " , TXT_SECRET_LEVEL , - Current_level_num , TXT_COMPLETE , Current_level_name , TXT_DESTROYED ) ;
else
sprintf ( title , " %s%s %d %s \n %s %s " , is_last_level ? " \n \n \n " : " \n " , TXT_LEVEL , Current_level_num , TXT_COMPLETE , Current_level_name , TXT_DESTROYED ) ;
Assert ( c < = N_GLITZITEMS ) ;
# ifdef NETWORK
if ( network & & ( Game_mode & GM_NETWORK ) )
2010-01-07 14:49:07 +00:00
newmenu_do2 ( NULL , title , c , m , multi_endlevel_poll1 , NULL , 0 , Menu_pcx_name ) ;
2006-03-20 16:43:15 +00:00
else
# endif // Note link!
2010-01-07 14:49:07 +00:00
newmenu_do2 ( NULL , title , c , m , NULL , NULL , 0 , Menu_pcx_name ) ;
2006-03-20 16:43:15 +00:00
}
2010-07-27 11:41:43 +00:00
int draw_rock ( newmenu * menu , d_event * event , grs_bitmap * background )
{
menu = menu ;
switch ( event - > type )
{
case EVENT_WINDOW_DRAW :
gr_set_current_canvas ( NULL ) ;
show_fullscr ( background ) ;
break ;
default :
break ;
}
return 0 ;
}
void do_screen_message ( char * fmt , . . . )
{
va_list arglist ;
grs_bitmap background ;
char msg [ 1024 ] ;
if ( Game_mode & GM_MULTI )
return ;
gr_init_bitmap_data ( & background ) ;
if ( pcx_read_bitmap ( Menu_pcx_name , & background , BM_LINEAR , gr_palette ) ! = PCX_ERROR_NONE )
return ;
gr_palette_load ( gr_palette ) ;
va_start ( arglist , fmt ) ;
vsprintf ( msg , fmt , arglist ) ;
va_end ( arglist ) ;
nm_messagebox1 ( NULL , ( int ( * ) ( newmenu * , d_event * , void * ) ) draw_rock , & background , 1 , TXT_OK , msg ) ;
gr_free_bitmap_data ( & background ) ;
}
2006-03-20 16:43:15 +00:00
//called when the player has finished a level
void PlayerFinishedLevel ( int secret_flag )
{
int rval ;
int was_multi = 0 ;
2010-06-27 11:28:26 +00:00
if ( Game_wind )
window_set_visible ( Game_wind , 0 ) ;
2006-03-20 16:43:15 +00:00
//credit the player for hostages
Players [ Player_num ] . hostages_rescued_total + = Players [ Player_num ] . hostages_on_board ;
# ifndef SHAREWARE
if ( ! ( Game_mode & GM_MULTI ) & & ( secret_flag ) ) {
newmenu_item m [ 1 ] ;
m [ 0 ] . type = NM_TYPE_TEXT ;
m [ 0 ] . text = " " ; //TXT_SECRET_EXIT;
2010-01-07 14:49:07 +00:00
newmenu_do2 ( NULL , TXT_SECRET_EXIT , 1 , m , NULL , NULL , 0 , Menu_pcx_name ) ;
2006-03-20 16:43:15 +00:00
}
# endif
// -- mk mk mk -- used to be here -- mk mk mk --
2009-11-28 07:51:06 +00:00
# ifdef NETWORK
2006-03-20 16:43:15 +00:00
if ( Game_mode & GM_NETWORK )
{
if ( secret_flag )
2009-11-24 09:48:53 +00:00
Players [ Player_num ] . connected = CONNECT_FOUND_SECRET ; // Finished and went to secret level
2006-03-20 16:43:15 +00:00
else
2009-11-24 09:48:53 +00:00
Players [ Player_num ] . connected = CONNECT_WAITING ; // Finished but did not die
2006-03-20 16:43:15 +00:00
}
2009-11-28 07:51:06 +00:00
# endif
2006-03-20 16:43:15 +00:00
last_drawn_cockpit = - 1 ;
if ( Current_level_num = = Last_level ) {
# ifdef NETWORK
if ( ( Game_mode & GM_MULTI ) & & ! ( Game_mode & GM_MULTI_COOP ) )
{
was_multi = 1 ;
multi_endlevel_score ( ) ;
rval = AdvanceLevel ( secret_flag ) ; //now go on to the next one (if one)
}
2010-06-14 08:13:16 +00:00
else
2006-03-20 16:43:15 +00:00
# endif
{ // Note link to above else!
rval = AdvanceLevel ( secret_flag ) ; //now go on to the next one (if one)
DoEndLevelScoreGlitz ( 0 ) ; //give bonuses
}
} else {
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
multi_endlevel_score ( ) ;
2010-06-14 08:13:16 +00:00
else
2006-03-20 16:43:15 +00:00
# endif // Note link!!
DoEndLevelScoreGlitz ( 0 ) ; //give bonuses
rval = AdvanceLevel ( secret_flag ) ; //now go on to the next one (if one)
}
if ( ! was_multi & & rval ) {
# ifndef SHAREWARE
2008-01-23 17:25:09 +00:00
if ( PLAYING_BUILTIN_MISSION )
2006-03-20 16:43:15 +00:00
# endif
scores_maybe_add_player ( 0 ) ;
2010-01-27 04:30:31 +00:00
if ( Game_wind )
window_close ( Game_wind ) ; // Exit out of game loop
2006-03-20 16:43:15 +00:00
}
2010-01-27 04:30:31 +00:00
else if ( rval & & Game_wind )
window_close ( Game_wind ) ;
2010-06-27 11:28:26 +00:00
if ( Game_wind )
window_set_visible ( Game_wind , 1 ) ;
2010-07-04 13:12:08 +00:00
reset_time ( ) ;
2006-03-20 16:43:15 +00:00
}
2010-06-14 08:13:16 +00:00
//from which level each do you get to each secret level
2008-01-23 17:25:09 +00:00
// int Secret_level_table[MAX_SECRET_LEVELS_PER_MISSION];
2006-03-20 16:43:15 +00:00
//called to go to the next level (if there is one)
//if secret_flag is true, advance to secret level, else next normal one
// Return true if game over.
int AdvanceLevel ( int secret_flag )
{
2009-07-01 11:35:33 +00:00
Control_center_destroyed = 0 ;
2006-03-20 16:43:15 +00:00
# ifdef EDITOR
2012-04-17 07:04:18 +00:00
if ( Current_level_num = = 0 )
2010-03-21 00:54:56 +00:00
{
2012-04-17 07:04:18 +00:00
return 1 ; //not a real level
2010-03-21 00:54:56 +00:00
}
2006-03-20 16:43:15 +00:00
# endif
2010-03-25 23:37:19 +00:00
key_flush ( ) ;
2006-03-20 16:43:15 +00:00
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
{
2010-03-21 00:54:56 +00:00
int result ;
2006-03-20 16:43:15 +00:00
result = multi_endlevel ( & secret_flag ) ; // Wait for other players to reach this point
if ( result ) // failed to sync
2010-03-21 00:54:56 +00:00
{
2006-03-20 16:43:15 +00:00
return ( Current_level_num = = Last_level ) ;
2010-03-21 00:54:56 +00:00
}
2006-03-20 16:43:15 +00:00
}
# endif
2010-03-25 23:37:19 +00:00
key_flush ( ) ;
2006-03-20 16:43:15 +00:00
if ( Current_level_num = = Last_level ) { //player has finished the game!
2010-06-14 08:13:16 +00:00
2006-03-20 16:43:15 +00:00
if ( ( Newdemo_state = = ND_STATE_RECORDING ) | | ( Newdemo_state = = ND_STATE_PAUSED ) )
newdemo_stop_recording ( ) ;
2010-03-25 23:37:19 +00:00
do_end_briefing_screens ( Ending_text_filename ) ;
2010-03-27 09:43:27 +00:00
2006-03-20 16:43:15 +00:00
return 1 ;
} else {
Next_level_num = Current_level_num + 1 ; //assume go to next normal level
if ( secret_flag ) { //go to secret level instead
int i ;
for ( i = 0 ; i < - Last_secret_level ; i + + )
if ( Secret_level_table [ i ] = = Current_level_num ) {
Next_level_num = - ( i + 1 ) ;
break ;
}
Assert ( i < - Last_secret_level ) ; //couldn't find which secret level
}
if ( Current_level_num < 0 ) { //on secret level, where to go?
Assert ( ! secret_flag ) ; //shouldn't be going to secret level
Assert ( Current_level_num < = - 1 & & Current_level_num > = Last_secret_level ) ;
Next_level_num = Secret_level_table [ ( - Current_level_num ) - 1 ] + 1 ;
}
StartNewLevel ( Next_level_num ) ;
}
2010-03-25 23:37:19 +00:00
key_flush ( ) ;
2006-03-20 16:43:15 +00:00
return 0 ;
}
//called when the player has died
void DoPlayerDead ( )
{
2010-06-27 11:28:26 +00:00
if ( Game_wind )
window_set_visible ( Game_wind , 0 ) ;
2006-03-20 16:43:15 +00:00
reset_palette_add ( ) ;
gr_palette_load ( gr_palette ) ;
dead_player_end ( ) ; //terminate death sequence (if playing)
# ifdef HOSTAGE_FACES
stop_all_hostage_clips ( ) ;
# endif
# ifdef EDITOR
if ( Game_mode = = GM_EDITOR ) { //test mine, not real level
object * player = & Objects [ Players [ Player_num ] . objnum ] ;
//nm_messagebox( "You're Dead!", 1, "Continue", "Not a real game, though." );
2012-04-16 06:41:26 +00:00
if ( Game_wind )
window_set_visible ( Game_wind , 1 ) ;
2006-03-20 16:43:15 +00:00
load_level ( " gamesave.lvl " ) ;
2012-04-15 13:32:46 +00:00
init_player_stats_new_ship ( Player_num ) ;
2006-03-20 16:43:15 +00:00
player - > flags & = ~ OF_SHOULD_BE_DEAD ;
StartLevel ( 0 ) ;
return ;
}
# endif
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
{
multi_do_death ( Players [ Player_num ] . objnum ) ;
}
2010-06-14 08:13:16 +00:00
else
# endif
2006-03-20 16:43:15 +00:00
{ //Note link to above else!
Players [ Player_num ] . lives - - ;
if ( Players [ Player_num ] . lives = = 0 )
2010-06-14 08:13:16 +00:00
{
2006-03-20 16:43:15 +00:00
DoGameOver ( ) ;
return ;
}
}
2010-06-14 08:13:16 +00:00
2009-07-01 11:35:33 +00:00
if ( Control_center_destroyed ) {
2006-03-20 16:43:15 +00:00
int rval ;
//clear out stuff so no bonus
Players [ Player_num ] . hostages_on_board = 0 ;
Players [ Player_num ] . energy = 0 ;
Players [ Player_num ] . shields = 0 ;
2009-11-28 07:51:06 +00:00
# ifdef NETWORK
2009-11-24 09:48:53 +00:00
Players [ Player_num ] . connected = CONNECT_DIED_IN_MINE ;
2009-11-28 07:51:06 +00:00
# endif
2006-03-20 16:43:15 +00:00
2010-07-27 11:41:43 +00:00
do_screen_message ( TXT_DIED_IN_MINE ) ; // Give them some indication of what happened
2006-03-20 16:43:15 +00:00
if ( Current_level_num = = Last_level ) {
# ifdef NETWORK
if ( ( Game_mode & GM_MULTI ) & & ! ( Game_mode & GM_MULTI_COOP ) )
{
multi_endlevel_score ( ) ;
rval = AdvanceLevel ( 0 ) ; //if finished, go on to next level
}
else
2010-06-14 08:13:16 +00:00
# endif
2006-03-20 16:43:15 +00:00
{ // Note link to above else!
rval = AdvanceLevel ( 0 ) ; //if finished, go on to next level
2010-06-14 08:13:16 +00:00
DoEndLevelScoreGlitz ( 0 ) ;
2006-03-20 16:43:15 +00:00
}
2012-04-15 13:32:46 +00:00
init_player_stats_new_ship ( Player_num ) ;
2006-03-20 16:43:15 +00:00
last_drawn_cockpit = - 1 ;
} else {
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
multi_endlevel_score ( ) ;
else
# endif
DoEndLevelScoreGlitz ( 0 ) ; // Note above link!
rval = AdvanceLevel ( 0 ) ; //if finished, go on to next level
2012-04-15 13:32:46 +00:00
init_player_stats_new_ship ( Player_num ) ;
2006-03-20 16:43:15 +00:00
last_drawn_cockpit = - 1 ;
}
if ( rval ) {
# ifndef SHAREWARE
2008-01-23 17:25:09 +00:00
if ( PLAYING_BUILTIN_MISSION )
2006-03-20 16:43:15 +00:00
# endif
scores_maybe_add_player ( 0 ) ;
2010-01-27 04:30:31 +00:00
if ( Game_wind )
window_close ( Game_wind ) ; // Exit out of game loop
2006-03-20 16:43:15 +00:00
}
} else {
2012-04-15 13:32:46 +00:00
init_player_stats_new_ship ( Player_num ) ;
2006-03-20 16:43:15 +00:00
StartLevel ( 1 ) ;
}
2010-06-27 11:28:26 +00:00
if ( Game_wind )
window_set_visible ( Game_wind , 1 ) ;
2010-07-04 13:12:08 +00:00
reset_time ( ) ;
2006-03-20 16:43:15 +00:00
}
//called when the player is starting a new level for normal game mode and restore state
void StartNewLevelSub ( int level_num , int page_in_textures )
{
if ( ! ( Game_mode & GM_MULTI ) ) {
last_drawn_cockpit = - 1 ;
}
if ( Newdemo_state = = ND_STATE_PAUSED )
Newdemo_state = ND_STATE_RECORDING ;
if ( Newdemo_state = = ND_STATE_RECORDING ) {
newdemo_set_new_level ( level_num ) ;
2008-10-16 17:27:02 +00:00
newdemo_record_start_frame ( FrameTime ) ;
2006-03-20 16:43:15 +00:00
}
LoadLevel ( level_num ) ;
if ( page_in_textures ) {
piggy_load_level_data ( ) ;
}
Assert ( Current_level_num = = level_num ) ; //make sure level set right
2010-06-14 08:13:16 +00:00
gameseq_init_network_players ( ) ; // Initialize the Players array for
2006-03-20 16:43:15 +00:00
// this level
# ifdef NETWORK
if ( Game_mode & GM_NETWORK )
{
2009-04-09 07:41:30 +00:00
if ( multi_level_sync ( ) ) // After calling this, Player_num is set
2010-06-29 21:14:30 +00:00
{
songs_play_song ( SONG_TITLE , 1 ) ; // level song already plays but we fail to start level...
2006-03-20 16:43:15 +00:00
return ;
2010-06-29 21:14:30 +00:00
}
2006-03-20 16:43:15 +00:00
}
# endif
HUD_clear_messages ( ) ;
automap_clear_visited ( ) ;
init_player_stats_level ( ) ;
2010-03-27 10:31:34 +00:00
gr_use_palette_table ( " palette.256 " ) ;
gr_palette_load ( gr_palette ) ;
2010-06-14 08:13:16 +00:00
2006-03-20 16:43:15 +00:00
# ifndef SHAREWARE
# ifdef NETWORK
if ( ( Game_mode & GM_MULTI_COOP ) & & Network_rejoined )
{
int i ;
for ( i = 0 ; i < N_players ; i + + )
Players [ i ] . flags | = Netgame . player_flags [ i ] ;
}
# endif
# endif
Viewer = & Objects [ Players [ Player_num ] . objnum ] ;
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
{
multi_prep_level ( ) ; // Removes robots from level if necessary
}
# endif
gameseq_remove_unused_players ( ) ;
Game_suspended = 0 ;
2009-07-01 11:35:33 +00:00
Control_center_destroyed = 0 ;
2006-03-20 16:43:15 +00:00
init_cockpit ( ) ;
init_robots_for_level ( ) ;
init_ai_objects ( ) ;
init_morphs ( ) ;
init_all_matcens ( ) ;
reset_palette_add ( ) ;
2011-02-14 21:27:02 +00:00
if ( ! ( Game_mode & GM_MULTI ) & & ! cheats . enabled )
2006-03-20 16:43:15 +00:00
set_highest_level ( Current_level_num ) ;
reset_special_effects ( ) ;
# ifdef OGL
ogl_cache_level_textures ( ) ;
# endif
# ifdef NETWORK
if ( Network_rejoined = = 1 )
{
Network_rejoined = 0 ;
StartLevel ( 1 ) ;
}
else
# endif
StartLevel ( 0 ) ; // Note link to above if!
copy_defaults_to_robot_all ( ) ;
init_controlcen_for_level ( ) ;
// Say player can use FLASH cheat to mark path to exit.
Last_level_path_created = - 1 ;
2010-06-14 08:13:16 +00:00
2010-02-05 02:31:36 +00:00
// Initialise for palette_restore()
if ( ! ( ( Game_mode & GM_MULTI ) & & ( Newdemo_state ! = ND_STATE_PLAYBACK ) ) )
palette_save ( ) ;
2010-06-14 08:13:16 +00:00
2010-02-08 05:34:43 +00:00
if ( ! Game_wind )
game ( ) ;
2006-03-20 16:43:15 +00:00
}
2011-01-14 13:29:36 +00:00
# ifdef NETWORK
extern char PowerupsInMine [ MAX_POWERUP_TYPES ] , MaxPowerupsAllowed [ MAX_POWERUP_TYPES ] ;
# endif
void bash_to_shield ( int i , char * s )
{
# ifdef NETWORK
int type = Objects [ i ] . id ;
# endif
# ifdef NETWORK
PowerupsInMine [ type ] = MaxPowerupsAllowed [ type ] = 0 ;
# endif
Objects [ i ] . id = POW_SHIELD_BOOST ;
Objects [ i ] . rtype . vclip_info . vclip_num = Powerup_info [ Objects [ i ] . id ] . vclip_num ;
Objects [ i ] . rtype . vclip_info . frametime = Vclip [ Objects [ i ] . rtype . vclip_info . vclip_num ] . frame_time ;
}
2006-03-20 16:43:15 +00:00
//called when the player is starting a new level for normal game model
void StartNewLevel ( int level_num )
{
2010-03-27 03:24:14 +00:00
hide_menus ( ) ;
2010-12-22 00:17:49 +00:00
GameTime64 = 0 ;
2011-01-14 16:56:14 +00:00
ThisLevelTime = 0 ;
2010-06-27 11:28:26 +00:00
2010-03-01 07:27:51 +00:00
if ( ! ( Game_mode & GM_MULTI ) ) {
do_briefing_screens ( Briefing_text_filename , level_num ) ;
2006-03-20 16:43:15 +00:00
}
2007-10-28 20:14:25 +00:00
StartNewLevelSub ( level_num , 1 ) ;
2006-03-20 16:43:15 +00:00
}
//initialize the player object position & orientation (at start of game, or new ship)
void InitPlayerPosition ( int random )
{
int NewPlayer = 0 ;
if ( ! ( ( Game_mode & GM_MULTI ) & & ! ( Game_mode & GM_MULTI_COOP ) ) ) // If not deathmatch
NewPlayer = Player_num ;
else if ( random = = 1 )
{
2011-05-22 17:54:44 +00:00
int i , trys = 0 ;
2006-03-20 16:43:15 +00:00
fix closest_dist = 0x7ffffff , dist ;
2011-02-02 22:51:29 +00:00
timer_update ( ) ;
d_srand ( ( fix ) timer_query ( ) ) ;
2006-03-20 16:43:15 +00:00
do {
trys + + ;
NewPlayer = d_rand ( ) % NumNetPlayerPositions ;
closest_dist = 0x7fffffff ;
2010-06-14 08:13:16 +00:00
2006-03-20 16:43:15 +00:00
for ( i = 0 ; i < N_players ; i + + ) {
if ( ( i ! = Player_num ) & & ( Objects [ Players [ i ] . objnum ] . type = = OBJ_PLAYER ) ) {
2011-02-02 22:51:29 +00:00
dist = find_connected_distance ( & Objects [ Players [ i ] . objnum ] . pos , Objects [ Players [ i ] . objnum ] . segnum , & Player_init [ NewPlayer ] . pos , Player_init [ NewPlayer ] . segnum , 15 , WID_FLY_FLAG ) ; // Used to be 5, search up to 15 segments
2006-03-20 16:43:15 +00:00
if ( ( dist < closest_dist ) & & ( dist > = 0 ) ) {
closest_dist = dist ;
}
}
}
2012-04-15 13:32:46 +00:00
} while ( ( closest_dist < i2f ( 15 * 20 ) ) & & ( trys < MAX_PLAYERS * 2 ) ) ;
2010-06-14 08:13:16 +00:00
}
2011-02-02 22:51:29 +00:00
else
{
// If deathmatch and not random, positions were already determined by sync packet
reset_player_object ( ) ;
reset_cruise ( ) ;
return ;
2006-03-20 16:43:15 +00:00
}
2011-02-02 22:51:29 +00:00
2006-03-20 16:43:15 +00:00
Assert ( NewPlayer > = 0 ) ;
Assert ( NewPlayer < NumNetPlayerPositions ) ;
ConsoleObject - > pos = Player_init [ NewPlayer ] . pos ;
ConsoleObject - > orient = Player_init [ NewPlayer ] . orient ;
2011-02-02 22:51:29 +00:00
obj_relink ( ConsoleObject - Objects , Player_init [ NewPlayer ] . segnum ) ;
2006-03-20 16:43:15 +00:00
reset_player_object ( ) ;
reset_cruise ( ) ;
}
// -----------------------------------------------------------------------------------------------------
// Initialize default parameters for one robot, copying from Robot_info to *objp.
// What about setting size!? Where does that come from?
void copy_defaults_to_robot ( object * objp )
{
robot_info * robptr ;
int objid ;
Assert ( objp - > type = = OBJ_ROBOT ) ;
objid = objp - > id ;
Assert ( objid < N_robot_types ) ;
robptr = & Robot_info [ objid ] ;
objp - > shields = robptr - > strength ;
}
// -----------------------------------------------------------------------------------------------------
// Copy all values from the robot info structure to all instances of robots.
// This allows us to change bitmaps.tbl and have these changes manifested in existing robots.
// This function should be called at level load time.
void copy_defaults_to_robot_all ( void )
{
int i ;
for ( i = 0 ; i < = Highest_object_index ; i + + )
if ( Objects [ i ] . type = = OBJ_ROBOT )
copy_defaults_to_robot ( & Objects [ i ] ) ;
}
int Do_appearance_effect = 0 ;
// -----------------------------------------------------------------------------------------------------
//called when the player is starting a level (new game or new ship)
void StartLevel ( int random )
{
Assert ( ! Player_is_dead ) ;
InitPlayerPosition ( random ) ;
verify_console_object ( ) ;
ConsoleObject - > control_type = CT_FLYING ;
ConsoleObject - > movement_type = MT_PHYSICS ;
disable_matcens ( ) ;
clear_transient_objects ( 0 ) ; //0 means leave proximity bombs
// create_player_appearance_effect(ConsoleObject);
Do_appearance_effect = 1 ;
# ifdef NETWORK
if ( Game_mode & GM_MULTI )
{
# ifndef SHAREWARE
if ( Game_mode & GM_MULTI_COOP )
multi_send_score ( ) ;
# endif
multi_send_reappear ( ) ;
2010-06-14 08:13:16 +00:00
}
2006-03-20 16:43:15 +00:00
if ( Game_mode & GM_NETWORK )
2009-03-20 12:10:38 +00:00
multi_do_protocol_frame ( 1 , 1 ) ;
2006-03-20 16:43:15 +00:00
# endif
ai_reset_all_paths ( ) ;
ai_init_boss_for_ship ( ) ;
reset_rear_view ( ) ;
Auto_fire_fusion_cannon_time = 0 ;
Fusion_charge = 0 ;
}