/*
* Initial version created by Dral 21 Aug 1999,
* based on kingdom code from Incoherent Dreams.
*/
// standard includes
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// mud includes
#include "merc.h"
#include "clantable.h"
// external vars
//extern bool fBootDb; // from db.c, true if the mud is still loading
// internal defines
#define CLANPK_CURRENT_FILEFORMAT_VERSION 3
#define CLANPK_DO_CLANTABLE_CLAN_NAME_LEGEND "clan name"
#define CLANPK_DO_CLANTABLE_CLAN_LEADER_NAME_LEGEND "leader"
#define CLANPK_DO_CLANTABLE_CLAN_COLEADER_NAME_LEGEND " coleader "
// internal structures
typedef struct clanpktable_data CLANPKTABLE_DATA;
struct clanpktable_data {
int num;
char *name;
char *leader_name;
char *coleader_name;
// number of times any member of this clan has ...
int kills; // ...killed a player who's not of this clan
int deaths; // ...been killed by a player who's not of this clan
int self_kills; // ...killed any other member of this clan
int clan_points;
int arena_kills;
int arena_deaths;
int arena_self_kills;
CLANPKTABLE_DATA *next;
};
// internal vars
static CLANPKTABLE_DATA *clanpk_list;
static CLANPKTABLE_DATA *clanless_clan; // normally same as first clan in clanpk_list
static bool loading_clanpktable;
static bool pending_save_clanpktable;
// internal functions
void save_clanpktable ();
CLANPKTABLE_DATA *create_clanpktable_data(char *clan_name, char *leader_name,char *coleader_name,
int kills, int deaths, int self_kills, int cp,
int arena_kills, int arena_deaths, int arena_self_kills);
CLANPKTABLE_DATA *get_clan_by_clanname (char *clan_name);
CLANPKTABLE_DATA *get_clan_by_char (CHAR_DATA *ch);
//CLANPKTABLE_DATA *get_clan_by_num (int num);
void internal_register_clanpk (CHAR_DATA *killer, CHAR_DATA *victim, bool is_arenakill);
void clanpktable__set_clan(CHAR_DATA *ch, CLANPKTABLE_DATA *clan);
void clanpktable__set_leader(CHAR_DATA *ch, CLANPKTABLE_DATA *clan);
void clanpktable__set_coleader(CHAR_DATA *ch, CLANPKTABLE_DATA *clan);
void dump_clantable();
//CLANPKTABLE_DATA *raw_get_clan_by_num(int num);
CLANPKTABLE_DATA *get_clanless_clan();
CLANPKTABLE_DATA *get_first_clan();
CLANPKTABLE_DATA *get_next_clan(CLANPKTABLE_DATA *a_clan);
//char *ratio2str(int value, int max, char *buf); // appends to buf and returns buf
void load_clanpktable ()
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
int i = 1;
int fileformat_version;
CLANPKTABLE_DATA *a_clan;
char *name;
char *leader_name;
char *coleader_name;
int kills;
int deaths;
int cp;
int self_kills;
int arena_kills;
int arena_deaths;
int arena_self_kills;
loading_clanpktable = TRUE;
pending_save_clanpktable = FALSE;
if ((fp = fopen (CLANTABLE_FILENAME, "r")) == NULL) {
sprintf (buf, "Error: load_clanpktable: %.200s not found!", CLANTABLE_FILENAME);
log_string (buf);
exit (1);
}
if (feof(fp)) {
log_string("Warning: load_clanpktable: empty clantable data file, no clans available");
// create a reasonable default entry for clan 0
a_clan = create_clanpktable_data("", "","", 0, 0, 0, 0, 0, 0, 0);
if (a_clan == NULL) {
log_string("Error: load_clanpktable: empty clantable data file...");
log_string("...and I couldn't even create a default clan");
fclose (fp);
exit (1);
}
}
fileformat_version = fread_number(fp);
fread_to_eol(fp);
if ( (fileformat_version < 1) || (fileformat_version > CLANPK_CURRENT_FILEFORMAT_VERSION) ) {
log_string("Error: load_clanpktable: unable to read clantable file...");
sprintf(buf, "...this version of load_clantable() can only read version 1 to %d files",
CLANPK_CURRENT_FILEFORMAT_VERSION);
fclose(fp);
exit (1);
}
if (fileformat_version == 1) {
// file format version 1 didn't include clan 0 stats
a_clan = create_clanpktable_data("", "","", 0, 0, 0, 0, 0, 0, 0);
if (a_clan == NULL) {
log_string("Error: load_clanpktable: reading ver 1 file: couldn't create the default clan");
fclose (fp);
exit (1);
}
save_clanpktable ();
i = 1;
} else {
i = 0;
}
for ( ; !feof(fp); i++) {
name = fread_string(fp); // 1: clan name
leader_name = fread_string(fp); // 2: leader name
coleader_name = fread_string(fp);
kills = fread_number(fp); // 3: clan kills
deaths = fread_number(fp); // 4: clan deaths
self_kills = fread_number(fp); // 5: clan self kills (intra clan kills)
if ( fileformat_version < 3 )
{
cp = 0;
arena_kills = 0;
arena_deaths = 0;
arena_self_kills = 0;
}
else
{
cp = fread_number(fp);
arena_kills = fread_number(fp); // 6: clan kills in arena
arena_deaths = fread_number(fp); // 7: clan deaths in arena
arena_self_kills = fread_number(fp); // 8: clan self kills (intra clan kills) in arena
}
a_clan = create_clanpktable_data(
name, // 1: clan name
leader_name, // 2: leader name
coleader_name,
kills, // 3: clan kills
deaths, // 4: clan deaths
self_kills, // 5: clan self kills (intra clan kills)
cp,
arena_kills, // 6: clan kills in arena
arena_deaths, // 7: clan deaths in arena
arena_self_kills // 8: clan self kills (intra clan kills) in arena
);
if (a_clan == NULL) {
sprintf(buf, "Error: load_clanpktable: couldn't create clan %d", i);
log_string(buf);
fclose (fp);
exit (1);
}
fread_to_eol(fp);
}
/*#ifdef MAGE_CLAN_NAME
if (get_clan_by_clanname(MAGE_CLAN_NAME) == NULL)
{
a_clan = create_clanpktable_data(MAGE_CLAN_NAME, "", 0, 0, 0, 0, 0, 0, 0);
if (a_clan == NULL)
{
sprintf(buf, "Error: load_clanpktable: mage clan \"%.30s\" didn't exist in %s",
MAGE_CLAN_NAME, CLANTABLE_FILENAME);
log_string(buf);
log_string ("Error: load_clanpktable: and an error occured trying to create it.");
fclose (fp);
exit (1);
}
sprintf(buf, "Warning: load_clanpktable: mage clan \"%.30s\" didn't exist in %s",
MAGE_CLAN_NAME, CLANTABLE_FILENAME);
log_string(buf);
log_string ("Warning: load_clanpktable: had to create it afresh with 0 in all stats.");
save_clanpktable ();
}
#endif*/
sprintf(buf, "debug: load_clanpktable: loaded %d clans from a version %d %s",
i, fileformat_version, CLANTABLE_FILENAME);
log_string(buf);
fclose (fp);
loading_clanpktable = FALSE;
#ifndef DEBUG_CLANPK
if ( pending_save_clanpktable || (fileformat_version < CLANPK_CURRENT_FILEFORMAT_VERSION) )
#endif
{
save_clanpktable();
}
}
// only need to call this in functions where clanpktable_data members
// are changed directly
void save_clanpktable ()
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
CLANPKTABLE_DATA *a_clan;
if (loading_clanpktable)
{
pending_save_clanpktable = TRUE;
return;
}
pending_save_clanpktable = FALSE;
fclose( fpReserve );
if ((fp = fopen (CLANTABLE_FILENAME, "w")) == NULL) {
sprintf (buf, "Error: unable to open %.200s for writing!", CLANTABLE_FILENAME);
log_string (buf);
if ( !loading_clanpktable )
{
fpReserve = fopen( NULL_FILE, "r" );
}
return;
}
// file format version
fprintf (fp, "3\n");
for (a_clan = get_first_clan(); a_clan != NULL; a_clan=get_next_clan(a_clan) ) {
fprintf (fp, "%s~\n", a_clan->name);
fprintf (fp, "%s~\n", a_clan->leader_name);
fprintf (fp, "%s~\n", a_clan->coleader_name);
fprintf (fp, "%d\n", a_clan->kills);
fprintf (fp, "%d\n", a_clan->deaths);
fprintf (fp, "%d\n", a_clan->self_kills);
fprintf (fp, "%d\n", a_clan->clan_points);
fprintf (fp, "%d\n", a_clan->arena_kills);
fprintf (fp, "%d\n", a_clan->arena_deaths);
fprintf (fp, "%d\n", a_clan->arena_self_kills);
}
fclose (fp);
fpReserve = fopen( NULL_FILE, "r" );
}
/* This is one of the few clan pk table functions that
* might return a NULL. It does this - rather than return
* clan 0 - to distinguish between not finding the named
* clan, and finding clan 0.
*/
CLANPKTABLE_DATA *get_clan_by_clanname (char *clan_name)
{
#ifdef DEBUG_CLANPK_VERBOSE
char buf[MAX_STRING_LENGTH];
#endif
CLANPKTABLE_DATA *a_clan;
if ( (clan_name == NULL) || (clan_name[0] == '\0') )
{
// please excuse this messy code - I'm tired
if (clan_name == NULL) {
bug("get_clan_by_name: NULL clan_name given", 0);
}
return get_clanless_clan();
}
for (a_clan=get_first_clan(); a_clan!=NULL; a_clan=get_next_clan(a_clan))
{
#ifdef DEBUG_CLANPK_VERBOSE
sprintf(buf, "get_clan_by_clanname: checking against clan %d", a_clan->num);
log_string(buf);
#endif
if (!str_cmp(a_clan->name, clan_name))
{
//clans[i].name == clan_name
//so we found the clan we're looking for
#ifdef DEBUG_CLANPK_VERBOSE
log_string("get_clan_by_clanname: found");
#endif
return a_clan;
}
}
// if we didn't return in the for loop, we didn't find the clan
// so return NULL to indicate failure
#ifdef DEBUG_CLANPK_VERBOSE
log_string("get_clan_by_clanname: not found");
#endif
return NULL;
}
CLANPKTABLE_DATA *get_clan_by_char (CHAR_DATA *ch)
{
#ifdef CHAR_CLANS_AS_NUMBER
int clan_num;
#else
char *clan_name;
#endif
char buf[MAX_STRING_LENGTH];
CLANPKTABLE_DATA *the_clan;
if (ch == NULL)
{
bug("get_clan_by_char: null char given", 0);
// if an invalid clan is found, return "clanless"/"final" (ie, no clan)
return get_clanless_clan();
}
clan_name = ch->clan;
if (clan_name == NULL)
{
clan_name = ch->clan = str_dup(get_clanless_clan()->name);
}
the_clan = get_clan_by_clanname(clan_name);
// if that clan doesn't exist...
if (the_clan == NULL)
{
// ...report that...
sprintf(buf, "get_clan_by_char: %s->clan=%.30s, doesn't exist, changing to clan 0",
ch->name, clan_name);
bug(buf, 0);
// ...and use the default clan
the_clan = get_clanless_clan();
clanpktable__set_clan(ch, the_clan);
}
return the_clan;
}
/*
CLANPKTABLE_DATA *get_clan_by_num (int clan_num)
{
int i;
char buf[MAX_STRING_LENGTH];
CLANPKTABLE_DATA *result;
if ( (clan_num<0) || (clan_num>=MAX_CLANS) )
{
sprintf(buf, "get_clan_by_num: %d out of range [0-%d]", clan_num, MAX_CLANS-1);
bug(buf, 0);
// if an invalid clan is found, return "clanless"/"rogue" (ie, no clan)
clan_num = 0;
}
result = raw_get_clan_by_num(clan_num);
i = result->num;
if ( i != clan_num )
{
CLANPKTABLE_DATA *other_clan = raw_get_clan_by_num(i);
sprintf(buf, "get_clan_by_num: clan %d[%.30s] thinks it's clan %d[%.30s]",
clan_num, result->name, i, (other_clan==NULL?"No such clan":other_clan->name));
bug(buf, 0);
// if an invalid clan is found, return "clanless"/"rogue" (ie, no clan)
result = raw_get_clan_by_num(0);
}
return result;
}
*/
/* This doesn't handle non-avatar related kills,
* mainly because they should never happen.
*/
void register_clanpk (CHAR_DATA *killer, CHAR_DATA *victim)
{
internal_register_clanpk(killer, victim, FALSE);
}
void register_arena_clanpk (CHAR_DATA *killer, CHAR_DATA *victim)
{
internal_register_clanpk(killer, victim, TRUE);
}
void internal_register_clanpk (CHAR_DATA *killer, CHAR_DATA *victim, bool is_arenakill)
{
char buf[MAX_STRING_LENGTH];
CLANPKTABLE_DATA *killer_clan, *victim_clan;
char *killer_name, *victim_name;
// most kills are players killing a mob, so check
// for that first
if ( IS_NPC(victim) || IS_NPC(killer) )
{
// ignore kills involving mobs
// TODO (maybe): check to see if the mob a clan guardian
// or charmed by anyone and, if so,
// calculate the real clans involved
return;
}
// this function mustn't be passed any NULL args
killer_name = (killer==NULL?"NULL":killer->name);
victim_name = (victim==NULL?"NULL":victim->name);
if ( (killer == NULL) || (victim == NULL) )
{
sprintf(buf, "register_clanpk: invalid args: killer=%s, victim=%s", killer_name, victim_name);
bug(buf, 0);
return;
}
// at this point we know this kill was a pk (player killing a player)
// check for clan numbers
// nb: we don't need to log invalid clans,
// because get_clan_by_num() already does
// this (and returns us clan 0 - clanless)
killer_clan = get_clan_by_char(killer);
victim_clan = get_clan_by_char(victim);
if (killer_clan == victim_clan)
{
// intra clan kill (self_kill)
if (killer_clan != get_clanless_clan())
{
// ohh! a clannie just killed one of their own!
// TODO: announce intra clan kill
}
if (is_arenakill)
{
killer_clan->arena_self_kills++;
}
else
{
killer_clan->self_kills++;
}
// nb: I don't add to deaths on purpose
// so to get all deaths you must look
// at deaths+self_kills
}
else
{
if (killer_clan->num != 0)
{
if (victim_clan->num != 0)
{
//TODO: announce clankill by killer_clan of victim_clan
}
else
{
//TODO (maybe): announce non-clankill by killer_clan
}
}
else if (victim_clan->num != 0)
{
//TODO (maybe): announce non-clandeath of victim_clan
}
if (is_arenakill)
{
killer_clan->arena_kills++;
victim_clan->arena_deaths++;
}
else
{
killer_clan->kills++;
killer_clan->clan_points += victim->race;
victim_clan->deaths++;
}
}
save_clanpktable();
}
void transfer_clanpk_leadership(CHAR_DATA *old_leader, CHAR_DATA *new_leader)
{
char buf[MAX_STRING_LENGTH];
CLANPKTABLE_DATA *clan_a;
CLANPKTABLE_DATA *clan_b;
if ( (old_leader==NULL) || (new_leader==NULL) )
{
sprintf(buf, "transfer_clanpk_leadership: old_leader==%.30s new_leader==%.30s - both much be non-NULL", (old_leader==NULL?"NULL":old_leader->name), (new_leader==NULL?"NULL":new_leader->name));
bug(buf, 0);
return;
}
clan_a = get_clan_by_char(old_leader);
clan_b = get_clan_by_char(new_leader);
if (clan_a != clan_b)
{
// the intended leader isn't in the same clan as the old leader.
// as leadership changing for some clans involves changes
// to ch->generation, I can't handle changing leader unless
// all other attribues have changed (eg, ch->clan and ch->generation)
sprintf(buf, "transfer_clanpk_leadership: old_leader \"%.30s\" is in clan \"%.30s\" but new_leader \"%.30s\" is in clan \"%.30s\" - they must be in the same clan _before_ leadership can be transfered by this function.", old_leader->name, new_leader->name, clan_a->name, clan_b->name);
bug(buf, 0);
return;
}
if (str_cmp(old_leader->name, clan_a->leader_name))
{
sprintf(buf, "transfer_clanpk_leadership: \"%.30s\" isn't the leader of \"%.30s\" - can't transfer leadership to \"%.30s\".", old_leader->name, clan_a->leader_name, new_leader->name);
bug(buf, 0);
return;
}
clanpktable__set_leader(new_leader, clan_a);
}
CLANPKTABLE_DATA *create_clanpktable_data(char *clan_name, char *leader_name,char *coleader,
int kills, int deaths, int self_kills, int cp,
int arena_kills, int arena_deaths, int arena_self_kills)
{
char buf[MAX_STRING_LENGTH];
CLANPKTABLE_DATA *a_clan, *new_clan = NULL;
if (clanpk_list == NULL) {
// this is the first clan created
// assume it's meant to be the "default" clan
// ie, the clan that people belong to if they're not in a clan
#ifdef DEBUG_CLANPK_VERBOSE
log_string("create_clanpktable_data: default clan (clan 0)");
#endif
} else {
// for all normal clans, have to check the name is unique
#ifdef DEBUG_CLANPK_VERBOSE
log_string("create_clanpktable_data: checking to see if another clan is using that name");
#endif
a_clan = get_clan_by_clanname(clan_name);
if (a_clan != NULL) {
sprintf(buf, "create_clanpktable_data: clan %.30s[%d] already uses that name",
a_clan->name, a_clan->num);
bug(buf, 0);
return NULL;
}
}
new_clan = (CLANPKTABLE_DATA *) malloc(sizeof(CLANPKTABLE_DATA));
if (new_clan == NULL)
{
sprintf(buf, "create_clanpktable_data: malloc: no memory to create clan: %.30s",
clan_name);
bug(buf, 0);
}
else
{
new_clan->name = str_dup(clan_name);
new_clan->leader_name = str_dup(leader_name);
new_clan->coleader_name = str_dup(coleader);
new_clan->kills = kills;
new_clan->deaths = deaths;
new_clan->self_kills = self_kills;
new_clan->clan_points = cp;
new_clan->arena_kills = arena_kills;
new_clan->arena_deaths = arena_deaths;
new_clan->arena_self_kills = arena_self_kills;
// add new clans to the end of the list,
// uses very slightly more cpu, but the
// list makes more sense (to me) that way
new_clan->next = NULL;
if (clanpk_list == NULL)
{
// if this is the first clan
clanless_clan = new_clan;
clanpk_list = new_clan;
new_clan->num = 0;
}
else
{
// find tail
for (a_clan=clanpk_list; (a_clan->next)!=NULL; a_clan=a_clan->next)
{
// do nothing, just loop through until a_clan is the last clan
}
// a_clan should now be the last clan in the list
a_clan->next = new_clan;
new_clan->num = a_clan->num + 1;
}
if (!loading_clanpktable)
{
save_clanpktable();
}
}
return new_clan;
}
void do_found_clan(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
//CLANPKTABLE_DATA *ch_clan;
CLANPKTABLE_DATA *new_clan;
if (IS_NPC(ch))
{
send_to_char("Sorry, an NPC may not found a clan.\n\r", ch);
return;
}
if ( !IS_IMMORTAL(ch) )
{
sprintf(buf, "Sorry, you don't have the power required to found a new clan.\n\r");
send_to_char(buf, ch);
return;
}
/*ch_clan = get_clan_by_char(ch);
if ( !str_cmp(ch->name, ch_clan->leader_name) )
{
send_to_char("You cannot found a new clan while you are the leader of your current clan:\n\r", ch);
sprintf(buf, " %s\n\r",
get_clan_by_char(ch)->name);
send_to_char(buf, ch);
return;
}*/
if (strlen(argument) < MIN_CLAN_NAME_LENGTH)
{
send_to_char("Clan name too short.\n\r", ch);
return;
}
if (strlen(argument) > MAX_CLAN_NAME_LENGTH)
{
argument[MAX_CLAN_NAME_LENGTH + 1] = '\0';
sprintf(buf, "Clan name too long, try \"%s\" instead.\n\r", argument);
send_to_char(buf, ch);
return;
}
smash_tilde(argument);
if ( get_clan_by_clanname(argument) != NULL )
{
send_to_char("A clan with that name already exists.\n\r", ch);
return;
}
// at this point, we know the clan:
// is being created by an immortal,
// has the right length name, which doesn't contain any tilde,
// doesn't already exist
// so lets go ahead and create the clan
new_clan = create_clanpktable_data(str_dup(argument), str_dup(""), str_dup(""),0, 0, 0, 0, 0, 0,0);
if (new_clan == NULL)
{
send_to_char("Eep! An internal error occured while trying to found your clan.\n\r", ch);
send_to_char("(Probably caused by there being too many clans.)\n\r", ch);
send_to_char("Please inform the admin ASAP.\n\r", ch);
return;
}
//don't do this any more, this function is now for immortal use only
//// and set ch as being a member
//clanpktable__set_clan(ch, new_clan);
sprintf(buf, "Created clan: %s\n\r", new_clan->name);
send_to_char(buf, ch);
}
void clanpktable__set_clan(CHAR_DATA *ch, CLANPKTABLE_DATA *clan)
{
#ifdef CHAR_CLANS_AS_NUMBER
ch->clan = clan->num;
#else
free_string(ch->clan);
ch->clan = str_dup(clan->name);
#endif
}
void clanpktable__set_leader(CHAR_DATA *ch, CLANPKTABLE_DATA *clan)
{
free_string ( clan->leader_name );
clan->leader_name = str_dup ( ch->name );
save_clanpktable ();
}
void clanpktable__set_coleader(CHAR_DATA *ch, CLANPKTABLE_DATA *clan)
{
free_string(clan->coleader_name);
clan->coleader_name = str_dup(ch->name);
save_clanpktable();
}
void do_clantable(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
int i;
int clan_count = 0;
float kill_ratio;
// should only need to be 5 (eg, "0.79\0")
// but this allows room for error
char ratio_buf[10];
int total_fights;
CLANPKTABLE_DATA *a_clan;
int max_clan_name_len;
int max_clan_leader_name_len;
int max_clan_coleader_name_len;
char horizontal_seperator[MAX_STRING_LENGTH];
int hs_pos; // index (POSition) withint the Horizontal_Seperator
int name_padding;
int leader_name_padding;
int coleader_padding;
max_clan_name_len = 0;
max_clan_leader_name_len = 0;
max_clan_coleader_name_len = 0;
for (a_clan=get_first_clan(); a_clan!=NULL; a_clan=get_next_clan(a_clan))
{
/* these shouldn't happen with get_next_clan
if (a_clan->num == -1) {
// unused slot
continue;
}
else if (a_clan->num != i)
{
// invalid clan
continue;
}
else
*/
if ( a_clan->num == 0 )
{
continue;
}
else
{
clan_count++;
if ( strlen(a_clan->name) > max_clan_name_len )
{
max_clan_name_len = strlen(a_clan->name);
}
if ( strlen(a_clan->leader_name) > max_clan_leader_name_len )
{
max_clan_leader_name_len = strlen(a_clan->leader_name);
}
}
}
if ( (max_clan_name_len+2) < strlen(CLANPK_DO_CLANTABLE_CLAN_NAME_LEGEND) )
{
max_clan_name_len = strlen(CLANPK_DO_CLANTABLE_CLAN_NAME_LEGEND) - 2;
}
if ( (max_clan_leader_name_len+2) < strlen(CLANPK_DO_CLANTABLE_CLAN_LEADER_NAME_LEGEND) )
{
max_clan_leader_name_len = strlen(CLANPK_DO_CLANTABLE_CLAN_LEADER_NAME_LEGEND) - 2;
}
if( (max_clan_coleader_name_len+2) < strlen(CLANPK_DO_CLANTABLE_CLAN_COLEADER_NAME_LEGEND) )
{
max_clan_coleader_name_len = strlen(CLANPK_DO_CLANTABLE_CLAN_COLEADER_NAME_LEGEND) - 2;
}
hs_pos = 0;
for (i = 0; i < (max_clan_name_len+2); i++)
{
horizontal_seperator[hs_pos++] = '-';
}
horizontal_seperator[hs_pos++] = '+';
for (i = 0; i < (max_clan_leader_name_len+2); i++)
{
horizontal_seperator[hs_pos++] = '-';
}
horizontal_seperator[hs_pos++] = '+';
for( i = 0; i < (max_clan_coleader_name_len+2); i++)
{
horizontal_seperator[hs_pos++] = '-';
}
horizontal_seperator[hs_pos++] = '+';
for (i = 0; i < strlen(" kills deaths ratio clanpoints "); i++)
{
horizontal_seperator[hs_pos++] = '-';
}
horizontal_seperator[hs_pos++] = '+';
for (i = 0; i < strlen(" awin aloss aintr "); i++)
{
horizontal_seperator[hs_pos++] = '-';
}
horizontal_seperator[hs_pos++] = '\0';
sprintf(buf, "/%s\\\n\r", horizontal_seperator);
send_to_char(buf, ch);
name_padding = (max_clan_name_len+2) - strlen(CLANPK_DO_CLANTABLE_CLAN_NAME_LEGEND);
leader_name_padding =
(max_clan_leader_name_len+2) - strlen(CLANPK_DO_CLANTABLE_CLAN_LEADER_NAME_LEGEND);
coleader_padding =
(max_clan_coleader_name_len+2) - strlen(CLANPK_DO_CLANTABLE_CLAN_COLEADER_NAME_LEGEND);
sprintf(buf, "|%*s%s%*s|%*s%s%*s|%*s%s%*s| kills deaths ratio clanpoints | awin aloss aintr |\n\r",
// left padding for "clan name"
( name_padding - (name_padding/2) ), "",
// "clan name"
CLANPK_DO_CLANTABLE_CLAN_NAME_LEGEND,
// right padding for "clan name"
( name_padding / 2 ), "",
// left padding for "leader"
( leader_name_padding - (leader_name_padding/2) ), "",
// "leader"
CLANPK_DO_CLANTABLE_CLAN_LEADER_NAME_LEGEND,
// right padding for "leader"
( leader_name_padding / 2 ), "",
// left padding co-leader
(coleader_padding - (coleader_padding/2)), "",
CLANPK_DO_CLANTABLE_CLAN_COLEADER_NAME_LEGEND,
( coleader_padding / 2 ), "");
send_to_char(buf, ch);
sprintf(buf, "+%s+\n\r", horizontal_seperator);
send_to_char(buf, ch);
for (a_clan=get_first_clan(); a_clan!=NULL; a_clan=get_next_clan(a_clan))
{
#ifdef DEBUG_CLANPK
sprintf(buf, "do_clantable: [%02d:%.20s]", a_clan->num, a_clan->name);
log_string(buf);
#endif
/* these shouldn't happen with get_next_clan
if (a_clan->num == -1) {
// unused slot
continue;
}
else if (a_clan->num != i)
{
// invalid clan
continue;
}
else
*/
if ( a_clan->num == 0 )
{
continue;
}
else
{
clan_count++;
total_fights = a_clan->kills + a_clan->deaths;
if ( total_fights < 1 )
{
sprintf(ratio_buf, "None");
}
else
{
kill_ratio = (float) a_clan->kills / total_fights;
sprintf(ratio_buf, "%1.2f", kill_ratio);
}
sprintf(buf, "| %-*.*s | %-*.12s | %-*.12s | %5d %5d %-.4s %10d | %5d %5d %5d |\n\r",
max_clan_name_len, MAX_CLAN_NAME_LENGTH, a_clan->name,
max_clan_leader_name_len, a_clan->leader_name,
max_clan_coleader_name_len, a_clan->coleader_name,
a_clan->kills, a_clan->deaths, ratio_buf,a_clan->clan_points,
a_clan->arena_kills, a_clan->arena_deaths, a_clan->arena_self_kills);
/*
sprintf(buf, " | %-18s | %-12s | %5d %5d %-.4s |\n\r",
a_clan->name, a_clan->leader_name, a_clan->kills, a_clan->deaths, ratio_buf);
*/
send_to_char(buf, ch);
}
}
sprintf(buf, "\\%s/\n\r", horizontal_seperator);
send_to_char(buf, ch);
/*
send_to_char(" \\--------------------+--------------+---------------------/\n\r", ch);
*/
}
void do_clanpk_leader(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char *old_leader_name;
CHAR_DATA *new_leader;
CLANPKTABLE_DATA *the_clan;
if ( !IS_IMMORTAL(ch) )
{
do_huh(ch, argument);
return;
}
new_leader = get_char_world(ch, argument);
if ( new_leader == NULL )
{
sprintf(buf, "Unable to find player \"%.30s\", are you sure they're loaded?",
argument);
send_to_char(buf, ch);
return;
}
if ( IS_NPC(new_leader) )
{
sprintf(buf, "No, \"%.30s\" is an NPC.", new_leader->name);
send_to_char(buf, ch);
return;
}
the_clan = get_clan_by_char(new_leader);
if ( the_clan == get_clanless_clan() )
{
sprintf(buf, "No, \"%.30s\" isn't in a clan.", new_leader->name);
send_to_char(buf, ch);
}
old_leader_name = the_clan->leader_name;
if (strlen(old_leader_name) == 0)
{
sprintf(buf, "Ok, giving leadership of \"%.30s\" to \"%.30s\".",
the_clan->name, new_leader->name);
}
else
{
sprintf(buf, "Ok, usurping \"%.30s\" in favour of \"%.30s\" as leader of \"%.30s\".",
the_clan->leader_name, new_leader->name, the_clan->name);
}
send_to_char(buf, ch);
if( !IS_SET(new_leader->clanbits, CLAN_LDR))
SET_BIT(new_leader->clanbits, CLAN_LDR);
if( IS_SET(new_leader->clanbits, CLAN_CO))
REMOVE_BIT(new_leader->clanbits, CLAN_CO);
clanpktable__set_leader(new_leader, the_clan);
}
void do_clanpk_coleader(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char *old_coleader_name;
CHAR_DATA *new_coleader;
CLANPKTABLE_DATA *the_clan;
if ( !IS_IMMORTAL(ch) )
{
do_huh(ch, argument);
return;
}
new_coleader = get_char_world(ch, argument);
if ( new_coleader == NULL )
{
sprintf(buf, "Unable to find player \"%.30s\", are you sure they're loaded?",
argument);
send_to_char(buf, ch);
return;
}
if ( IS_NPC(new_coleader) )
{
sprintf(buf, "No, \"%.30s\" is an NPC.", new_coleader->name);
send_to_char(buf, ch);
return;
}
the_clan = get_clan_by_char(new_coleader);
if ( the_clan == get_clanless_clan() )
{
sprintf(buf, "No, \"%.30s\" isn't in a clan.", new_coleader->name);
send_to_char(buf, ch);
}
old_coleader_name = the_clan->coleader_name;
if (strlen(old_coleader_name) == 0)
{
sprintf(buf, "Ok, giving co-leadership of \"%.30s\" to \"%.30s\".",
the_clan->name, new_coleader->name);
}
else
{
sprintf(buf, "Ok, usurping \"%.30s\" in favour of \"%.30s\" as co-leader of \"%.30s\".",
the_clan->coleader_name, new_coleader->name, the_clan->name);
}
send_to_char(buf, ch);
if( !IS_SET(new_coleader->clanbits, CLAN_CO))
SET_BIT(new_coleader->clanbits, CLAN_CO);
if( IS_SET(new_coleader->clanbits, CLAN_LDR))
REMOVE_BIT(new_coleader->clanbits, CLAN_LDR);
clanpktable__set_coleader(new_coleader, the_clan);
}
void dump_clantable()
{
char buf[MAX_STRING_LENGTH];
int clan_count = 0;
CLANPKTABLE_DATA *a_clan;
log_string("/--------|--------------------+--------------+---------------\\");
log_string("| i/num | clan name | leader | kills deaths |");
log_string("+--------|--------------------+--------------+---------------+");
for (a_clan=get_first_clan(); a_clan!=NULL; a_clan=get_next_clan(a_clan))
{
clan_count++;
sprintf(buf, "| %02d/%02d | %-18s | %-12s | %5d %5d |",
clan_count, a_clan->num,
a_clan->name, a_clan->leader_name,
a_clan->kills, a_clan->deaths);
log_string(buf);
}
log_string("\\--------|--------------------+--------------+---------------/");
}
/*
CLANPKTABLE_DATA *raw_get_clan_by_num(int num)
{
CLANPKTABLE *cur;
CLANPKTABLE *prev;
int i;
#ifdef DEBUG_CLANPK_VERBOSE
char buf[MAX_STRING_LENGTH];
sprintf(buf, "raw_get_clan_by_num(%d)", num);
log_string(buf);
#endif
cur = prev = clanpk_list;
for (i=0; (i<num) && (cur!=NULL); i++) {
prev = cur;
cur = cur->next;
}
return cur;
}
*/
CLANPKTABLE_DATA *get_clanless_clan()
{
return clanless_clan;
}
CLANPKTABLE_DATA *get_first_clan()
{
#ifdef DEBUG_CLANPK_VERBOSE
char buf[MAX_STRING_LENGTH];
#endif
CLANPKTABLE_DATA *a_clan;
a_clan = clanpk_list;
#ifdef DEBUG_CLANPK_VERBOSE
sprintf(buf, "get_first_clan: [%02d:%.20s]", a_clan->num, a_clan->name);
log_string(buf);
#endif
return a_clan;
}
CLANPKTABLE_DATA *get_next_clan(CLANPKTABLE_DATA *a_clan)
{
#ifdef DEBUG_CLANPK
char buf[MAX_STRING_LENGTH];
#endif
CLANPKTABLE_DATA *another_clan = NULL;
if (a_clan == NULL)
{
// should probably bug() here
return NULL;
}
another_clan = a_clan->next;
#ifdef DEBUG_CLANPK
if (another_clan == NULL)
{
sprintf(buf, "get_next_clan: exiting, no next clan found");
}
else
{
sprintf(buf, "get_next_clan: [%02d:%.20s]",
another_clan->num, another_clan->name);
}
log_string(buf);
#endif
return another_clan;
}
/*
// appends to buf and returns buf
char *ratio2str(int value, int max, char *buf)
{
// but that has p
if ( max < 1 )
{
sprintf(buf, "None");
}
else if ( value < 1 )
{
sprint(buf, "0.00");
}
else if ( value >= max )
{
sprint(buf, "1.00");
}
else
{
// would probably be better to use sprintf with a "%02f"
sprintf(buf, "0.%02d", (int)((value*100)/max));
}
return buf;
}
*/