/**************************************************************************/
// pload.cpp - dawn player loading/unloading system
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "pload.h"
void extract_char_from_char_list(char_data *ch);
int ploaded_players_in_realm=0;
/**************************************************************************/
char_data *pload_find_player_by_name(char *name)
{
// the following lines are an optimisation so everytime a player
// logs in we don't have to search every player in every room
if(ploaded_players_in_realm<=0){
return NULL;
}
// loop thru all players in all rooms looking for ploaded players
int i;
ROOM_INDEX_DATA *pRoomIndex;
for(i=0; i<MAX_KEY_HASH; i++){
for ( pRoomIndex = room_index_hash[i];pRoomIndex;pRoomIndex = pRoomIndex->next ){
for(char_data *lch=pRoomIndex->people; lch; lch=lch->next_in_room){
if(lch->pload && !IS_NPC(lch)){
if(!str_cmp(name, lch->name)){
return lch;
}
}
}
}
}
// unfound
return NULL;
}
/**************************************************************************/
// extract a ploaded player, without saving them
void pload_extract(char_data *ch, char_data *victim)
{
if(!victim){
ch->println("pload_extract(): bug, victim is NULL!");
logf("pload_extract(): bug, victim is NULL!");
return;
}
if(!victim->pload){
ch->println("pload_extract(): victim->pload is NULL!");
logf("pload_extract(): victim->pload is NULL!");
return;
}
char_from_room(victim);
if(victim->pet){
char_from_room(victim->pet);
}
if(victim->pload->loaded_by && victim->pload->loaded_by!=ch){
victim->pload->loaded_by->printlnf("`YPloaded character '%s' has been unloaded by '%s'`x",
PERS(victim, victim->pload->loaded_by),
ch?PERS(ch, victim->pload->loaded_by):"player login?!?");
}
ch->printlnf("Ploaded character '%s' has been unloaded.", PERS(victim, ch));
// deallocate the pload relationship recording
if(victim->pload->loaded_by){
victim->pload->loaded_by->ploaded=NULL;
victim->pload->loaded_by=NULL;
delete victim->pload;
victim->pload=NULL;
}
if(victim->pet){
if(victim->pet->pload){
delete victim->pet->pload;
victim->pet->pload=NULL;
}
free_char( victim->pet );
}
free_char( victim );
ploaded_players_in_realm--;
}
/**************************************************************************/
void do_goto( char_data *ch, char *argument );
/**************************************************************************/
// Kal - Dec 2001
void do_pload(char_data *ch, char *argument )
{
char_data *lch;
if(IS_NPC(ch) || ch->pload){
ch->println("live players only sorry.");
return;
}
char arg[MIL];
char name[MIL];
argument=one_argument(argument, arg);
one_argument(argument, name);
if(IS_NULLSTR(arg)){
ch->titlebar("PLAYER LOAD SYNTAX AND NOTES");
ch->println("syntax: pload load <playername> - load a player");
ch->println("syntax: pload unload <playername> - removes a ploaded player");
ch->println("syntax: pload save <playername> - saves a ploaded player pfile");
ch->println("syntax: pload list <playername> - lists all currently ploaded players");
ch->println("");
ch->println("`xNotes about a ploaded player:");
ch->println("* Any changes you do to the player will NOT be saved,\r\n"
" unless you use the `=Cpload save`x command");
ch->println("* The 'unload' option does NOT save the ploaded players pfile.");
ch->println("* Ploaded players can not be seen by mortals");
ch->println("* Time does NOT pass for the player, so affect durations will be unaffected");
ch->println("* The player will automatically be unloaded (without saving) when you logout.");
ch->println("* The player will automatically be unloaded (without saving)\r\n"
" if they try to login and get their password correct.");
ch->println("* Ploaded players are put in limbo by default, if you move them from this\r\n"
" room and 'pload save' them, they will appear in the new room next login");
ch->println("* A players ploaded login is not recorded in laston.");
ch->println("* A players login time, site and hours played remain what\r\n"
" they were with their last normal login.");
ch->println("* Ploaded players are not transfered nor saved for a hotreboot.");
ch->println("* Often the ploaded player can only be located while in the same\r\n"
" room as it, or using the 'pload list' command.");
ch->println("* With some functions, ploaded player names must be used in full.");
ch->titlebar("");
return;
}
// load option
if(!str_cmp(arg,"load")){
connection_data d;
memset(&d, 0, sizeof(d));
d.make_connected_socket_invalid();
bool pfile_loaded_okay;
if(IS_NULLSTR(name)){
do_pload(ch,""); // show the help - incomplete syntax
return;
}
ROOM_INDEX_DATA *limbo=get_room_index( ROOM_VNUM_LIMBO );
assertp(limbo); // should be impossible to not have a limbo room
// imms must be in the limbo room to pload players
if(ch->in_room!=limbo){
ch->printlnf("You must be in limbo (room %d) to load players with pload.",
ROOM_VNUM_LIMBO);
ch->println("Moving you to limbo for the pload.");
interpret(ch, FORMATF("goto %d",ROOM_VNUM_LIMBO));
if(ch->in_room!=limbo){
ch->printlnf("The command 'goto %d' failed to get you to limbo, manually goto limbo then retry pload.",
ROOM_VNUM_LIMBO);
return;
}
}
// can't pload more than one at a time.
if(ch->ploaded){
ch->printlnf("You have already ploaded '%s' who is in room %d.",
ch->ploaded->name, ch->ploaded->in_room->vnum);
return;
}
// confirm no player is in the game with exactly that name
for( lch = player_list; lch; lch = lch->next_player ){
if(!str_cmp(lch->name, name)){
if(can_see_who(ch, lch)){
ch->printlnf("'%s' is already within the game.", name);
}else{
ch->printlnf("'%s' is above your level/trust - you can not pload him/her.", name);
}
return;
}
}
// confirm that character isn't ploaded by someone else
if(pload_find_player_by_name(name)){
ch->printlnf("'%s' is already ploaded by someone else.", name);
do_pload(ch,"list");
return;
}
// attempt to load the pfile
pfile_loaded_okay= load_char_obj( &d, name );
if(!pfile_loaded_okay || !d.character){
ch->printlnf("Couldn't load pfile '%s'.", name);
return;
}
// pfile loaded, check if they are above the trust/level of the loader
lch=d.character;
d.character->desc=NULL;
if(lch->pet){
// remove pets from the char_list
extract_char_from_char_list(lch->pet);
}
if(get_trust(ch)<=get_trust(lch)){
// notice that this message should be the same as the one above, if the loader
// cant see the loaded person when they are already in the game
ch->printlnf("'%s' is above your level/trust - you can not pload him/her.", name);
// deallocate the loaded character data
if(lch->pet){
free_char( lch->pet );
}
free_char( lch );
return;
}
// === By This Stage:
// * we have loaded the pfile data into lch
// * lch->in_room is set to the room the player would normally be loaded into
// * if they have a pet:
// - pet is read into lch->pet,
// - lch->pet->in_room is set to the room the pet would normally be loaded into
// Transfer the player into the limbo room, save the was_in_room field first though
// as this simulates the affect of the player going idle and being transfered to
// limbo naturally... as a result when the player is saved, they will be saved in their
// original room.
lch->was_in_room=lch->in_room;
char_to_room(lch, limbo);
ch->printlnf("Character %s ploaded - original room %d.",
PERS(lch, ch), lch->was_in_room?lch->was_in_room->vnum:-1);
logf("Character '%s' ploaded - will save in original room (%d).",
PERS(lch, NULL), lch->was_in_room?lch->was_in_room->vnum:-1);
if(lch->pet){
lch->pet->was_in_room=lch->pet->in_room;
char_to_room(lch->pet, limbo);
ch->printlnf("Pet '%s' belonging to %s ploaded - original room %d.",
PERS(lch->pet, ch), PERS(lch, ch), lch->pet->was_in_room?lch->pet->was_in_room->vnum:-1);
logf("Pet '%s' belonging to %s ploaded - original room vnum %d.",
PERS(lch->pet, NULL), PERS(lch, NULL), lch->pet->was_in_room?lch->pet->was_in_room->vnum:-1);
}
// record the pload relationship
ch->ploaded=lch;
lch->pload=new pload_data;
lch->pload->dont_save=true; // we dont want the pfile saved
lch->pload->loaded_by=ch;
lch->next=NULL;
lch->next_player=NULL;
ploaded_players_in_realm++;
if(lch->pet){
lch->pet->pload=new pload_data;
lch->pet->pload->loaded_by=NULL;
lch->pet->next=NULL;
lch->pet->next_player=NULL;
}
// NOTE: neither pets nor characters are within the player_list or character_list
// This is intentional - so they arent affected by char_update() etc
return;
}
// unload option
if(!str_cmp(arg,"unload")){
if(IS_NULLSTR(name)){
do_pload(ch,""); // show the help - incomplete syntax
return;
}
lch=get_char_room(ch, name);
if(!lch){
ch->printlnf("There is no ploaded player '%s' to unload from this room.", name);
return;
}
if(IS_NPC(lch)){
ch->printlnf("'%s' is an NPC, you can't use pload to unload them.", name);
return;
}
if(!lch->pload){
ch->printlnf("'%s' was not ploaded, so you can't unload him/her.", name);
return;
}
pload_extract(ch, lch);
return;
}
// save option
if(!str_cmp(arg,"save")){
if(IS_NULLSTR(name)){
do_pload(ch,""); // show the help - incomplete syntax
return;
}
lch=get_char_room(ch, name);
if(!lch){
ch->wraplnf("There is no ploaded player '%s' to save in this room "
"(you must be in the same room as a ploaded player to save them).", name);
do_pload(ch,"list");
return;
}
if(IS_NPC(lch)){
ch->printlnf("'%s' is an NPC, you can't use pload to save them.", name);
return;
}
if(!lch->pload){
ch->printlnf("'%s' was not ploaded, so you can't save him/her.", name);
return;
}
lch->pload->dont_save=false; // we dont want the pfile saved
save_char_obj(lch);
lch->pload->dont_save=true; // we dont want the pfile saved
ch->printlnf("saved ploaded player '%s'", lch->name);
logf("saved ploaded player '%s'", lch->name);
return;
}
// list option
if(!str_cmp(arg,"list")){
ROOM_INDEX_DATA *limbo=get_room_index( ROOM_VNUM_LIMBO );
assertp(limbo); // should be impossible to not have a limbo room
// loop thru all players in all rooms looking for ploaded players
int i;
int count=0;
int pccount=0;
ROOM_INDEX_DATA *pRoomIndex;
for(i=0; i<MAX_KEY_HASH; i++){
for ( pRoomIndex = room_index_hash[i];pRoomIndex;pRoomIndex = pRoomIndex->next ){
for(lch=pRoomIndex->people; lch; lch=lch->next_in_room){
if(lch->pload){
ch->printf("[%d] %s in room %d ",
++count,
PERS(lch, ch),
pRoomIndex->vnum);
if(lch->in_room==limbo && lch->was_in_room){
ch->printf("[save room %d] ", lch->was_in_room->vnum);
}else{
ch->printf("[save room %d] ", lch->in_room->vnum);
}
if(lch->pload->loaded_by){
ch->printlnf("(loaded by %s)", PERS(lch->pload->loaded_by, ch));
}else{
if(IS_NPC(lch) && lch->master && lch->master->pet==lch){
ch->printlnf("(pet of %s)", PERS(lch->master, ch));
}else{
ch->println("(loaded by unknown)");
}
}
if(!IS_NPC(lch)){
pccount++;
}
}
}
}
}
if(count==0){
ch->println("There are no ploaded players in the game");
}
if(pccount!=ploaded_players_in_realm){
logf("do_pload(): bug - count!=ploaded_players_in_realm!!!");
ch->println("do_pload(): bug - count!=ploaded_players_in_realm!!!");
}
return;
}
ch->printlnf("Unknown pload command '%s'", arg);
do_pload(ch, "");
}
/**************************************************************************/
// Kal, Aug 02
void do_undeny( char_data *ch, char *argument )
{
if(IS_NULLSTR(argument)){
ch->println("syntax: undeny <playername>");
ch->println("This command is really a macro for:`1"
" pload load <playername>`1"
" undeny <playername>`1"
" pload save <playername>`1"
" pload unload <playername>");
return;
}
char_data *victim;
// check the player isn't already around
victim=get_whovis_player_world(ch, argument);
if(victim){
ch->printlnf("player '%s' is already in the game.", argument);
return;
}
victim=pload_find_player_by_name(argument);
if(victim){
ch->printlnf("ploaded player by name '%s' already in the game.", argument);
return;
}
// backup the room they are already in
room_index_data *rm=ch->in_room;
ROOM_INDEX_DATA *limbo=get_room_index( ROOM_VNUM_LIMBO );
assertp(limbo); // should be impossible to not have a limbo room
ch->println("UNDENY BEGINS");
// imms must be in the limbo room to pload players
if(rm!=limbo){
ch->println("Moving you to limbo for the pload.");
char_from_room(ch);
char_to_room(ch, limbo);
}
ch->println("Ploading victim.");
interpret(ch, FORMATF("pload load %s", argument));
victim=pload_find_player_by_name(argument);
if(!victim || IS_NPC(victim)){
ch->println("Something went wrong with the pload, victim not found");
ch->println("Punloading victim.");
interpret(ch, FORMATF("pload unload %s", argument));
if(ch->in_room!=rm){
ch->println("Returning you to old room.");
char_from_room(ch);
char_to_room(ch, rm);
}
ch->println("UNDENY ABORTED");
return;
}
if(!IS_SET(victim->act, PLR_DENY)){
ch->println("VICTIM IS NOT CURRENTLY DENIED!");
ch->println("Punloading victim.");
interpret(ch, FORMATF("pload unload %s", argument));
if(ch->in_room!=rm){
ch->println("Returning you to old room.");
char_from_room(ch);
char_to_room(ch, rm);
}
ch->println("UNDENY ABORTED");
return;
}
REMOVE_BIT(victim->act, PLR_DENY);
ch->println("DENY FLAG REMOVED FROM VICTIM.");
ch->println("Saving victim.");
interpret(ch, FORMATF("pload save %s", argument));
ch->println("Punloading victim.");
interpret(ch, FORMATF("pload unload %s", argument));
if(ch->in_room!=rm){
ch->println("Returning you to old room.");
char_from_room(ch);
char_to_room(ch, rm);
}
ch->println("UNDENY FINISHED");
}
/**************************************************************************/
/**************************************************************************/