mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
402 lines
10 KiB
C++
402 lines
10 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
--- HISTORICAL COMMENTS FOLLOW ---
|
|
|
|
* $Logfile: /DescentIII/Main/Dmfc/dmfcpinfo.cpp $
|
|
* $Revision: 1.1.1.1 $
|
|
* $Date: 2003/08/26 03:57:21 $
|
|
* $Author: kevinb $
|
|
*
|
|
* DMFC Playerinfo class
|
|
*
|
|
* $Log: dmfcpinfo.cpp,v $
|
|
* Revision 1.1.1.1 2003/08/26 03:57:21 kevinb
|
|
* initial 1.5 import
|
|
*
|
|
*
|
|
* 21 7/09/99 2:54p Jeff
|
|
* handle gametime better (pause it when needed) if the server is 'waiting
|
|
* for players'
|
|
*
|
|
* 20 7/07/99 6:10p Jeff
|
|
* don't count the time that a player is in observer mode for death/kill
|
|
* messages
|
|
*
|
|
* 19 5/13/99 4:55p Ardussi
|
|
* changes for compiling on the Mac
|
|
*
|
|
* 18 5/12/99 11:05p Jeff
|
|
* dmfc and multiplayer games now have endian friendly packets (*whew*)
|
|
*
|
|
* 17 4/25/99 7:19p Jeff
|
|
* added code to handle suicides in pinfo
|
|
*
|
|
* 16 3/17/99 12:25p Jeff
|
|
* converted DMFC to be COM interface
|
|
*
|
|
* 15 2/11/99 12:51a Jeff
|
|
* changed names of exported variables
|
|
*
|
|
* 13 9/30/98 3:50p Jeff
|
|
* general improvements (many)
|
|
*
|
|
* 12 9/29/98 3:04p Jeff
|
|
* added time in game and start_time support
|
|
*
|
|
* 11 9/25/98 8:02p Jason
|
|
* added checks for jeff
|
|
*
|
|
* 10 9/25/98 7:56p Jeff
|
|
* fixed the hosing of the data in UnpackData
|
|
*
|
|
* 9 9/25/98 7:25p Jeff
|
|
*
|
|
* 8 9/25/98 4:50p Jeff
|
|
*
|
|
* 7 9/24/98 5:52p Jeff
|
|
* starting adding statistical death messages, checked in for testing
|
|
*
|
|
* 6 9/21/98 7:11p Jeff
|
|
* made InputCommand interface API and moved existing input commands to
|
|
* the interface. Changed mprintf/ASSERT so they are valid in DMFC
|
|
*
|
|
* 5 8/04/98 3:29p Jeff
|
|
* completion of player records. Moved Pinfo to player records...anyone
|
|
* can save detailed stats of the game now
|
|
*
|
|
* 4 7/28/98 2:04p Jeff
|
|
*
|
|
* 3 7/22/98 12:13p Jeff
|
|
* keep track of who you kill now...plus save memory with a name table
|
|
*
|
|
* 2 7/19/98 7:23p Jeff
|
|
* added support to keep track of who kills who
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "gamedll_header.h"
|
|
#include "DMFC.h"
|
|
#include "dmfcinternal.h"
|
|
#include <string.h>
|
|
|
|
extern DMFCBase *basethis;
|
|
|
|
PInfo::PInfo(int slot) {
|
|
m_slot = slot;
|
|
|
|
extra_info.last_kill_time = 0;
|
|
extra_info.last_death_time = 0;
|
|
extra_info.kill_time = 0;
|
|
extra_info.death_time = 0;
|
|
extra_info.observer_time = 0;
|
|
extra_info.kills_in_a_row = 0;
|
|
extra_info.deaths_in_a_row = 0;
|
|
extra_info.last_kill_num = -1;
|
|
extra_info.last_death_num = -1;
|
|
extra_info.got_revenge = 0;
|
|
|
|
killer_list = NULL;
|
|
curr = NULL;
|
|
|
|
curr = CreateKiller(slot); // Setup Suicide
|
|
if (curr)
|
|
curr->kills = 0;
|
|
}
|
|
|
|
PInfo::~PInfo(void) {
|
|
tPKillerInfo *curr, *next;
|
|
curr = next = killer_list;
|
|
|
|
while (curr) {
|
|
next = curr->next;
|
|
free(curr);
|
|
curr = next;
|
|
}
|
|
}
|
|
|
|
tPKillerInfo *PInfo::GetKillerInfo(int slot) {
|
|
tPKillerInfo *info;
|
|
info = FindKiller(slot);
|
|
return info;
|
|
}
|
|
|
|
void PInfo::Update(int slot, tPKillerInfo *amount) {
|
|
tPKillerInfo *info;
|
|
|
|
info = FindKiller(slot);
|
|
if (!info) {
|
|
// new one
|
|
info = CreateKiller(slot);
|
|
if (!info)
|
|
return;
|
|
}
|
|
info->kills += amount->kills;
|
|
}
|
|
|
|
void PInfo::HandleKill(int victim_num) {
|
|
extra_info.last_kill_time = extra_info.kill_time;
|
|
extra_info.kill_time = basethis->GetRealGametime();
|
|
extra_info.kills_in_a_row++;
|
|
extra_info.deaths_in_a_row = 0;
|
|
extra_info.last_kill_num = victim_num;
|
|
}
|
|
|
|
void PInfo::HandleDeath(int killer_num) {
|
|
extra_info.got_revenge = 0;
|
|
extra_info.last_death_time = extra_info.death_time;
|
|
extra_info.death_time = basethis->GetRealGametime();
|
|
extra_info.deaths_in_a_row++;
|
|
extra_info.kills_in_a_row = 0;
|
|
extra_info.last_death_num = killer_num;
|
|
}
|
|
|
|
void PInfo::HandleSuicide(void) {
|
|
extra_info.got_revenge = 1; // mark it so they don't get a revenge message
|
|
extra_info.last_death_time = extra_info.death_time;
|
|
extra_info.death_time = basethis->GetRealGametime();
|
|
extra_info.deaths_in_a_row++;
|
|
extra_info.kills_in_a_row = 0;
|
|
}
|
|
|
|
tPExtraInfo *PInfo::GetExtraInfo(void) { return &extra_info; }
|
|
|
|
tPKillerInfo *PInfo::GetFirstKiller(void) {
|
|
curr = killer_list;
|
|
return killer_list;
|
|
}
|
|
|
|
tPKillerInfo *PInfo::GetNextKiller(void) {
|
|
if (!curr)
|
|
return NULL;
|
|
if (!curr->next)
|
|
return NULL;
|
|
curr = curr->next;
|
|
return curr;
|
|
}
|
|
|
|
tPKillerInfo *PInfo::FindKiller(int slot, tPKillerInfo **wprev) {
|
|
tPKillerInfo *curr;
|
|
tPKillerInfo *prev;
|
|
curr = killer_list;
|
|
prev = NULL;
|
|
|
|
while (curr) {
|
|
|
|
if (slot == curr->slot) {
|
|
// we found a match
|
|
break;
|
|
}
|
|
|
|
prev = curr;
|
|
curr = curr->next;
|
|
}
|
|
|
|
if (wprev)
|
|
*wprev = prev;
|
|
return curr;
|
|
}
|
|
|
|
tPKillerInfo *PInfo::CreateKiller(int slot) {
|
|
tPKillerInfo *curr, *prev;
|
|
curr = FindKiller(slot, &prev);
|
|
|
|
if (!curr) {
|
|
if (prev) {
|
|
// the name wasn't in the list so we can tack it on here at the end
|
|
curr = (tPKillerInfo *)malloc(sizeof(tPKillerInfo));
|
|
if (!curr)
|
|
return NULL;
|
|
prev->next = curr;
|
|
} else {
|
|
// no names in the list
|
|
curr = killer_list = (tPKillerInfo *)malloc(sizeof(tPKillerInfo));
|
|
if (!killer_list)
|
|
return NULL;
|
|
}
|
|
|
|
curr->next = NULL;
|
|
curr->kills = 0;
|
|
curr->slot = slot;
|
|
}
|
|
|
|
return curr;
|
|
}
|
|
|
|
void PInfo::RemoveKiller(int slot) {
|
|
tPKillerInfo *curr, *prev;
|
|
curr = FindKiller(slot, &prev);
|
|
|
|
if (curr) {
|
|
if (prev) {
|
|
prev->next = curr->next;
|
|
free(curr);
|
|
} else {
|
|
// we're removing root (odd...this is yourself)
|
|
ASSERT(!prev); // Get Jeff
|
|
killer_list = curr->next;
|
|
free(curr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PInfo::ResetAll(void) {
|
|
tPKillerInfo *c, *next;
|
|
c = next = killer_list;
|
|
|
|
while (c) {
|
|
next = c->next;
|
|
free(c);
|
|
c = next;
|
|
}
|
|
curr = killer_list = NULL;
|
|
|
|
extra_info.last_kill_time = 0;
|
|
extra_info.last_death_time = 0;
|
|
extra_info.kill_time = 0;
|
|
extra_info.death_time = 0;
|
|
extra_info.observer_time = 0;
|
|
extra_info.kills_in_a_row = 0;
|
|
extra_info.deaths_in_a_row = 0;
|
|
extra_info.last_kill_num = -1;
|
|
extra_info.last_death_num = -1;
|
|
extra_info.got_revenge = 0;
|
|
}
|
|
|
|
int PInfo::GetExtraInfoSize(void) {
|
|
int size = 0;
|
|
|
|
size += sizeof(float); // extrainfo.last_kill_time
|
|
size += sizeof(float); // extrainfo.last_death_time
|
|
size += sizeof(float); // extra_info.observer_time
|
|
size += sizeof(float); // extrainfo.kill_time
|
|
size += sizeof(float); // extrainfo.death_time
|
|
size += sizeof(uint16_t); // extrainfo.kills_in_a_row
|
|
size += sizeof(uint16_t); // extrainfo.deaths_in_a_row
|
|
size += sizeof(int8_t); // extrainfo.last_kill_num
|
|
size += sizeof(int8_t); // extrainfo.last_death_num
|
|
size += sizeof(char); // extrainfo.got_revenge
|
|
|
|
return size;
|
|
}
|
|
|
|
int PInfo::GetSizeOfData(void) {
|
|
tPKillerInfo *c;
|
|
c = killer_list;
|
|
int size = 0;
|
|
|
|
size = 0;
|
|
while (c) {
|
|
size += sizeof(int); // kills
|
|
size++; // slot
|
|
c = c->next;
|
|
}
|
|
|
|
size += GetExtraInfoSize();
|
|
|
|
return size;
|
|
}
|
|
|
|
void PInfo::PackData(uint8_t *buffer) {
|
|
if (!buffer)
|
|
return;
|
|
tPKillerInfo *c;
|
|
c = killer_list;
|
|
int count = 0;
|
|
|
|
MultiAddFloat(extra_info.last_kill_time, buffer, &count);
|
|
MultiAddFloat(extra_info.last_death_time, buffer, &count);
|
|
MultiAddFloat(extra_info.kill_time, buffer, &count);
|
|
MultiAddFloat(extra_info.death_time, buffer, &count);
|
|
MultiAddFloat(extra_info.observer_time, buffer, &count);
|
|
MultiAddUshort(extra_info.kills_in_a_row, buffer, &count);
|
|
MultiAddUshort(extra_info.deaths_in_a_row, buffer, &count);
|
|
MultiAddByte(extra_info.last_kill_num, buffer, &count);
|
|
MultiAddByte(extra_info.last_death_num, buffer, &count);
|
|
MultiAddByte(extra_info.got_revenge, buffer, &count);
|
|
|
|
while (c) {
|
|
ASSERT(c->slot >= 0 && c->slot < 64);
|
|
MultiAddByte(c->slot, buffer, &count); // slot
|
|
MultiAddInt(c->kills, buffer, &count);
|
|
c = c->next;
|
|
}
|
|
}
|
|
|
|
bool PInfo::UnpackData(uint8_t *buffer, int buffsize) {
|
|
if (!buffer)
|
|
return false;
|
|
int count = 0;
|
|
int slot, kills;
|
|
bool done = false;
|
|
tPKillerInfo *k;
|
|
ResetAll();
|
|
|
|
// buffsize is taking into account extra info, which is guaranteed to be in there
|
|
extra_info.last_kill_time = MultiGetFloat(buffer, &count);
|
|
extra_info.last_death_time = MultiGetFloat(buffer, &count);
|
|
extra_info.kill_time = MultiGetFloat(buffer, &count);
|
|
extra_info.death_time = MultiGetFloat(buffer, &count);
|
|
extra_info.observer_time = MultiGetFloat(buffer, &count);
|
|
extra_info.kills_in_a_row = MultiGetUshort(buffer, &count);
|
|
extra_info.deaths_in_a_row = MultiGetUshort(buffer, &count);
|
|
extra_info.last_kill_num = MultiGetByte(buffer, &count);
|
|
extra_info.last_death_num = MultiGetByte(buffer, &count);
|
|
extra_info.got_revenge = MultiGetByte(buffer, &count);
|
|
|
|
int t_size = sizeof(int) + GetExtraInfoSize() + 1;
|
|
if (buffsize < t_size) // not even 1 slot in here
|
|
done = true;
|
|
|
|
while (!done) {
|
|
slot = MultiGetByte(buffer, &count); // slot
|
|
kills = MultiGetInt(buffer, &count); // kills
|
|
|
|
if (count >= buffsize)
|
|
done = true;
|
|
|
|
ASSERT(slot >= 0 && slot < MAX_PLAYER_RECORDS);
|
|
k = CreateKiller(slot);
|
|
if (k) {
|
|
k->kills = kills;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void PInfo::EnterObserverMode(void) { extra_info.observer_time = basethis->GetRealGametime(); }
|
|
|
|
void PInfo::ExitObserverMode(void) {
|
|
ASSERT(extra_info.observer_time > 0);
|
|
float observe_time = (basethis->GetRealGametime()) - extra_info.observer_time;
|
|
extra_info.observer_time = 0;
|
|
|
|
if (extra_info.last_kill_time > 0)
|
|
extra_info.last_kill_time += observe_time;
|
|
|
|
if (extra_info.last_death_time > 0)
|
|
extra_info.last_death_time += observe_time;
|
|
|
|
if (extra_info.kill_time > 0)
|
|
extra_info.kill_time += observe_time;
|
|
|
|
if (extra_info.death_time > 0)
|
|
extra_info.death_time += observe_time;
|
|
}
|