diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/ai.c d1x-rebirth_v0.58.1-src/main/ai.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/ai.c 2013-07-18 12:33:15.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/ai.c 2018-12-24 14:41:53.612079500 +0100 @@ -1602,6 +1602,7 @@ Players[Player_num].num_robots_level++; Players[Player_num].num_robots_total++; + Players[Player_num].num_robots_level_spawn++; return 1; } diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/collide.c d1x-rebirth_v0.58.1-src/main/collide.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/collide.c 2013-04-22 12:04:48.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/collide.c 2018-12-24 17:02:08.051798100 +0100 @@ -864,6 +864,11 @@ Players[Player_num].num_kills_level++; Players[Player_num].num_kills_total++; + if (robot->matcen_creator) // spawned by matcen or dropped by robot? + Players[Player_num].num_kills_level_spawn++; + if (Newdemo_state == ND_STATE_RECORDING) + newdemo_record_num_kills(Players[Player_num].num_kills_level, Players[Player_num].num_kills_total, + Players[Player_num].num_kills_level_spawn); if (Robot_info[robot->id].boss_flag) { start_boss_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL); diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/fireball.c d1x-rebirth_v0.58.1-src/main/fireball.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/fireball.c 2013-06-08 17:41:19.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/fireball.c 2018-12-24 13:50:45.114757600 +0100 @@ -817,6 +817,8 @@ obj->ctype.ai_info.CURRENT_STATE = AIS_LOCK; obj->ctype.ai_info.GOAL_STATE = AIS_LOCK; obj->ctype.ai_info.REMOTE_OWNER = -1; + + obj->matcen_creator = ROBOT_DROP_MATCEN_NUM; } break; diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/fireball.h d1x-rebirth_v0.58.1-src/main/fireball.h --- ../osrc/d1x-rebirth_v0.58.1-src/main/fireball.h 2013-04-22 12:02:58.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/fireball.h 2018-12-24 17:45:08.045910000 +0100 @@ -83,6 +83,8 @@ #define ET_MULTI_START 1 //first part of multi-part explosion #define ET_MULTI_SECOND 2 //second part of multi-part explosion +#define ROBOT_DROP_MATCEN_NUM -2 + object *object_create_explosion(short segnum, vms_vector *position, fix size, int vclip_type); object *object_create_muzzle_flash(short segnum, vms_vector *position, fix size, int vclip_type); diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/fuelcen.c d1x-rebirth_v0.58.1-src/main/fuelcen.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/fuelcen.c 2013-04-22 12:02:58.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/fuelcen.c 2018-12-24 14:41:51.523168300 +0100 @@ -300,6 +300,7 @@ Players[Player_num].num_robots_level++; Players[Player_num].num_robots_total++; + Players[Player_num].num_robots_level_spawn++; objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos, &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad, diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/gamerend.c d1x-rebirth_v0.58.1-src/main/gamerend.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/gamerend.c 2013-06-27 11:28:34.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/gamerend.c 2018-12-24 15:11:26.258304300 +0100 @@ -76,15 +76,8 @@ } #endif -void show_framerate() -{ - static int fps_count = 0, fps_rate = 0; +static int lower_text_y_pos() { int y = GHEIGHT; - static fix64 fps_time = 0; - - gr_set_curfont(GAME_FONT); - gr_set_fontcolor(BM_XRGB(0,31,0),-1); - if (PlayerCfg.CockpitMode[1] == CM_FULL_SCREEN) { if ((Game_mode & GM_MULTI) || (Newdemo_state == ND_STATE_PLAYBACK && Newdemo_game_mode & GM_MULTI)) y -= LINE_SPACING * 10; @@ -101,6 +94,16 @@ else y -= LINE_SPACING * 2; } + return y; +} + +void show_framerate() +{ + static int fps_count = 0, fps_rate = 0; + static fix64 fps_time = 0; + + gr_set_curfont(GAME_FONT); + gr_set_fontcolor(BM_XRGB(0,31,0),-1); fps_count++; if (timer_query() >= fps_time + F1_0) @@ -109,7 +112,20 @@ fps_count = 0; fps_time = timer_query(); } - gr_printf(SWIDTH-(GameArg.SysMaxFPS>999?FSPACX(43):FSPACX(37)),y,"FPS: %i",fps_rate); + gr_printf(SWIDTH-(GameArg.SysMaxFPS>999?FSPACX(43):FSPACX(37)),lower_text_y_pos(),"FPS: %i",fps_rate); +} + +void show_robot_kills() +{ + if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) ) + return; + + gr_set_curfont(GAME_FONT); + gr_set_fontcolor(BM_XRGB(0,31,0),-1); + + gr_printf(FSPACX(1),lower_text_y_pos(),"Kills: %i+%i", + Players[Player_num].num_kills_level - Players[Player_num].num_kills_level_spawn, + Players[Player_num].num_kills_level_spawn); } #ifdef NETWORK @@ -331,6 +347,8 @@ if (GameCfg.FPSIndicator && PlayerCfg.CockpitMode[1] != CM_REAR_VIEW) show_framerate(); + show_robot_kills(); + if (Newdemo_state == ND_STATE_PLAYBACK) Game_mode = Newdemo_game_mode; diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/gamesave.c d1x-rebirth_v0.58.1-src/main/gamesave.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/gamesave.c 2013-06-30 20:41:07.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/gamesave.c 2018-12-24 18:26:44.495582700 +0100 @@ -353,6 +353,7 @@ //reads one object of the given version from the given file void read_object(object *obj,PHYSFS_file *f,int version) { + memset(obj, 0, sizeof(*obj)); obj->type = PHYSFSX_readByte(f); obj->id = PHYSFSX_readByte(f); diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/gameseq.c d1x-rebirth_v0.58.1-src/main/gameseq.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/gameseq.c 2013-06-27 11:28:34.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/gameseq.c 2018-12-24 17:05:52.295912800 +0100 @@ -255,6 +255,7 @@ Players[pnum].net_kills_total = 0; Players[pnum].num_kills_level = 0; Players[pnum].num_kills_total = 0; + Players[pnum].num_kills_level_spawn = 0; Players[pnum].num_robots_level = 0; Players[pnum].num_robots_total = 0; Players[pnum].KillGoalCount = 0; @@ -306,8 +307,14 @@ Players[Player_num].killer_objnum = -1; Players[Player_num].num_kills_level = 0; + Players[Player_num].num_kills_level_spawn = 0; + if (Newdemo_state == ND_STATE_RECORDING) + newdemo_record_num_kills(Players[Player_num].num_kills_level, Players[Player_num].num_kills_total, + Players[Player_num].num_kills_level_spawn); + 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].num_robots_level_spawn = 0; Players[Player_num].hostages_level = count_number_of_hostages(); Players[Player_num].hostages_total += Players[Player_num].hostages_level; diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/gameseq.h d1x-rebirth_v0.58.1-src/main/gameseq.h --- ../osrc/d1x-rebirth_v0.58.1-src/main/gameseq.h 2013-04-22 12:02:58.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/gameseq.h 2018-12-24 15:15:43.752862800 +0100 @@ -112,4 +112,6 @@ void bash_to_shield(int, char *); +int count_number_of_robots(void); + #endif /* _GAMESEQ_H */ diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/gauges.c d1x-rebirth_v0.58.1-src/main/gauges.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/gauges.c 2013-06-27 11:28:34.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/gauges.c 2018-12-18 19:37:23.999712200 +0100 @@ -725,6 +725,13 @@ gr_set_fontcolor(Color_0_31_0, -1); gr_string(grd_curcanv->cv_bitmap.bm_w-w-FSPACX(1), FSPACY(1), score_str); + + /* + if ( !((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) ) { + sprintf(score_str, "%s: %5d", "Kills", Players[Player_num].num_kills_level); + gr_string(grd_curcanv->cv_bitmap.bm_w-w-FSPACX(1), FSPACY(9), score_str); + } + */ } void hud_show_timer_count() diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/newdemo.c d1x-rebirth_v0.58.1-src/main/newdemo.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/newdemo.c 2013-06-30 20:41:07.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/newdemo.c 2018-12-24 17:09:22.546139100 +0100 @@ -130,6 +130,7 @@ #define ND_EVENT_LASER_LEVEL 42 // with old/new level #define ND_EVENT_LINK_SOUND_TO_OBJ 43 // record digi_link_sound_to_object3 #define ND_EVENT_KILL_SOUND_TO_OBJ 44 // record digi_kill_sound_linked_to_object +#define ND_EVENT_NUM_KILLS 45 // sized, with old level, old total, new level, new total #define NORMAL_PLAYBACK 0 #define SKIP_PLAYBACK 1 @@ -145,6 +146,7 @@ #define DEMO_GAME_TYPE_SHAREWARE 1 #define DEMO_GAME_TYPE 2 +#define DEMO_HAS_SIZED 4 // added to game-type to indicate sized extensions // In- and Out-files PHYSFS_file *infile; @@ -188,6 +190,9 @@ static fix nd_record_v_homing_distance = -1; static int nd_record_v_primary_ammo = -1; static int nd_record_v_secondary_ammo = -1; +static int nd_record_v_num_kills_level = -1; +static int nd_record_v_num_kills_total = -1; +static int nd_record_v_num_kills_level_spawn = -1; void newdemo_record_oneframeevent_update(int wallupdate); extern int digi_link_sound_to_object3( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance, int loop_start, int loop_end ); @@ -821,7 +826,7 @@ stop_time(); nd_write_byte(ND_EVENT_START_DEMO); nd_write_byte(DEMO_VERSION); - nd_write_byte(DEMO_GAME_TYPE); + nd_write_byte(DEMO_GAME_TYPE | DEMO_HAS_SIZED); nd_write_fix(0); // NOTE: This is supposed to write GameTime (in fix). Since our GameTime64 is fix64 and the demos do not NEED this time actually, just write 0. #ifdef NETWORK @@ -862,6 +867,8 @@ nd_record_v_homing_distance = -1; nd_record_v_primary_ammo = -1; nd_record_v_secondary_ammo = -1; + nd_record_v_num_kills_level = -1; + nd_record_v_num_kills_total = -1; for (i = 0; i < MAX_PRIMARY_WEAPONS; i++) nd_write_short((short)Players[Player_num].primary_ammo[i]); @@ -884,6 +891,8 @@ nd_write_byte((sbyte)Primary_weapon); nd_write_byte((sbyte)Secondary_weapon); nd_record_v_start_frame = nd_record_v_frame_number = 0; + newdemo_record_num_kills(Players[Player_num].num_kills_level, Players[Player_num].num_kills_total, + Players[Player_num].num_kills_level_spawn); newdemo_set_new_level(Current_level_num); newdemo_record_oneframeevent_update(1); start_time(); @@ -1322,6 +1331,25 @@ start_time(); } +void newdemo_record_num_kills(int num_kills_level, int num_kills_total, int num_kills_level_spawn) +{ + stop_time(); + nd_write_byte(ND_EVENT_NUM_KILLS); + nd_write_short(6 * 4); + nd_write_int(nd_record_v_num_kills_level < 0 ? num_kills_level : nd_record_v_num_kills_level); + nd_write_int(nd_record_v_num_kills_total < 0 ? num_kills_total : nd_record_v_num_kills_total); + nd_write_int(num_kills_level); + nd_write_int(num_kills_total); + nd_record_v_num_kills_level = num_kills_level; + nd_record_v_num_kills_total = num_kills_total; + + nd_write_int(nd_record_v_num_kills_level_spawn < 0 ? num_kills_level_spawn : nd_record_v_num_kills_level_spawn); + nd_write_int(num_kills_level_spawn); + nd_record_v_num_kills_level_spawn = num_kills_level_spawn; + + start_time(); +} + void newdemo_set_new_level(int level_num) { @@ -1407,6 +1435,7 @@ return 1; } nd_read_byte(&game_type); + game_type &= ~DEMO_HAS_SIZED; if (purpose == PURPOSE_REWRITE) nd_write_byte(game_type); if ((game_type == DEMO_GAME_TYPE_SHAREWARE) && shareware) @@ -2540,6 +2569,50 @@ break; } + case ND_EVENT_NUM_KILLS: { + int old_level, old_total, new_level, new_total, old_spawn, new_spawn; + short size; + + nd_read_short(&size); + nd_read_int(&old_level); + nd_read_int(&old_total); + nd_read_int(&new_level); + nd_read_int(&new_total); + if (size >= 6 * 4) + { + nd_read_int(&old_spawn); + nd_read_int(&new_spawn); + } + else + { + old_spawn = new_spawn = 0; + } + if (rewrite) + { + nd_write_short(size); + nd_write_int(old_level); + nd_write_int(old_total); + nd_write_int(new_level); + nd_write_int(new_total); + if (size >= 6 * 4) + { + nd_write_int(old_spawn); + nd_write_int(new_spawn); + } + break; + } + if ((Newdemo_vcr_state == ND_STATE_REWINDING) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEBACKWARD)) { + Players[Player_num].num_kills_level = old_level; + Players[Player_num].num_kills_total = old_total; + Players[Player_num].num_kills_level_spawn = old_spawn; + } else if ((Newdemo_vcr_state == ND_STATE_PLAYBACK) || (Newdemo_vcr_state == ND_STATE_FASTFORWARD) || (Newdemo_vcr_state == ND_STATE_ONEFRAMEFORWARD)) { + Players[Player_num].num_kills_level = new_level; + Players[Player_num].num_kills_total = new_total; + Players[Player_num].num_kills_level_spawn = new_spawn; + } + break; + } + case ND_EVENT_NEW_LEVEL: { sbyte new_level, old_level, loaded_level; @@ -2595,9 +2668,15 @@ break; } - default: + default: { + short size; + sbyte x; + nd_read_short(&size); + while (size--) + nd_read_byte(&x); Int3(); } + } } // Now set up cockpit and views according to what we read out. Note that the demo itself cannot determinate the right views since it does not use a good portion of the real game code. diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/newdemo.h d1x-rebirth_v0.58.1-src/main/newdemo.h --- ../osrc/d1x-rebirth_v0.58.1-src/main/newdemo.h 2013-06-30 20:41:07.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/newdemo.h 2018-12-24 17:00:30.224997100 +0100 @@ -91,6 +91,7 @@ extern void newdemo_record_secondary_ammo(int new_ammo); extern void newdemo_record_door_opening(int segnum, int side); extern void newdemo_record_laser_level(sbyte old_level, sbyte new_level); +extern void newdemo_record_num_kills(int num_kills_level, int num_kills_total, int num_kills_level_spawn); // Functions called during playback process... extern void newdemo_object_move_all(); diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/player.h d1x-rebirth_v0.58.1-src/main/player.h --- ../osrc/d1x-rebirth_v0.58.1-src/main/player.h 2013-04-22 12:02:58.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/player.h 2018-12-24 14:40:51.131668700 +0100 @@ -108,6 +108,8 @@ fix homing_object_dist; // Distance of nearest homing object. sbyte hours_level; // Hours played (since time_total can only go up to 9 hours) sbyte hours_total; // Hours played (since time_total can only go up to 9 hours) + short num_kills_level_spawn; // Number of kills this level of spawned robots + short num_robots_level_spawn; // Number of spawned robots this level } __pack__ player; // Same as above but structure how Savegames expect diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/state.c d1x-rebirth_v0.58.1-src/main/state.c --- ../osrc/d1x-rebirth_v0.58.1-src/main/state.c 2013-08-03 12:51:17.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/state.c 2018-12-24 15:39:45.663355300 +0100 @@ -1218,6 +1218,8 @@ //Read player info StartNewLevelSub(current_level, 1, 0);//use page_in_textures here to fix OGL texture precashing crash -MPM + int orig_robot_count = count_number_of_robots(); + MALLOC(pl_rw, player_rw, 1); PHYSFS_read(fp, pl_rw, sizeof(player_rw), 1); player_rw_swap(pl_rw, swap); @@ -1489,6 +1491,18 @@ window_set_visible(Game_wind, 1); reset_time(); + // infer spawned robot kills + int cur_robot_spawn_count = 0, cur_robot_count = 0; + for (i = 0; i <= Highest_object_index; i++) + if (Objects[i].type == OBJ_ROBOT && !(Objects[i].flags & (OF_EXPLODING | OF_SHOULD_BE_DEAD))) { + if (Objects[i].matcen_creator) + cur_robot_spawn_count++; + cur_robot_count++; + } + int non_spawn_kills = orig_robot_count - (cur_robot_count - cur_robot_spawn_count); + Players[Player_num].num_kills_level_spawn = Players[Player_num].num_kills_level - non_spawn_kills; + Players[Player_num].num_robots_level_spawn = Players[Player_num].num_kills_level_spawn + cur_robot_spawn_count; + return 1; } diff -ur ../osrc/d1x-rebirth_v0.58.1-src/main/vers_id.h d1x-rebirth_v0.58.1-src/main/vers_id.h --- ../osrc/d1x-rebirth_v0.58.1-src/main/vers_id.h 2013-07-18 12:33:38.000000000 +0200 +++ d1x-rebirth_v0.58.1-src/main/vers_id.h 2018-12-24 17:57:01.853817400 +0100 @@ -9,9 +9,10 @@ #define DXX_VERSION_MAJOR __stringize(DXX_VERSION_MAJORi) #define DXX_VERSION_MINOR __stringize(DXX_VERSION_MINORi) #define DXX_VERSION_MICRO __stringize(DXX_VERSION_MICROi) +#define DXX_REVISION "-ar3" #define BASED_VERSION "Registered v1.5 Jan 5, 1996" -#define VERSION DXX_VERSION_MAJOR "." DXX_VERSION_MINOR "." DXX_VERSION_MICRO +#define VERSION DXX_VERSION_MAJOR "." DXX_VERSION_MINOR "." DXX_VERSION_MICRO DXX_REVISION #define DESCENT_VERSION g_descent_version extern const char g_descent_version[40];