/**************************************************************************/
// chardata.cpp - implementation of char_data member functions
/***************************************************************************
* 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 all the licenses *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************
* >> Original Diku Mud copyright (c)1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, & Katja Nyboe. *
* >> Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* >> ROM 2.4 is copyright 1993-1995 Russ Taylor and has been brought to *
* you by the ROM consortium: Russ Taylor(rtaylor@pacinfo.com), *
* Gabrielle Taylor(gtaylor@pacinfo.com) & Brian Moore(rom@rom.efn.org) *
* >> Oblivion 1.2 is copyright 1996 Wes Wagner *
**************************************************************************/
#include "include.h"
#include "chardata.h"
void flush_cached_write_to_buffer(connection_data *d);
/**************************************************************************/
void queue_print(int seconds, char_data *ch, const char *text);
/**************************************************************************/
// just send it to the characters output buffer
void char_data::print(const char *txt)
{
char *buf=(char *)txt;
if(!this){
return;
}
if(m_pdelay){
queue_print(m_pdelay, this, buf);
}else{
process_moblog(this, buf);
if ( IS_NULLSTR(buf) || !this->desc){
return;
}
write_to_buffer( this->desc, buf, str_len(buf) );
}
}
/**************************************************************************/
// the delay all the print style commands by this amount
int char_data::pdelay()
{
return m_pdelay;
};
/**************************************************************************/
void char_data::set_pdelay(int seconds)
{
m_pdelay=seconds;
};
/**************************************************************************/
void char_data::printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
print(temp_HSL_workspace);
}
/**************************************************************************/
void char_data::printfbw(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
printbw(temp_HSL_workspace);
}
/**************************************************************************/
void char_data::printf(int seconds, const char *fmt, ...)
{
if(!this){
return;
}
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
m_pdelay=seconds;
print(temp_HSL_workspace);
m_pdelay=0;
}
/**************************************************************************/
// send b+w text
void char_data::printbw(const char *buf)
{
if(!this){
return;
}
if(m_pdelay){
queue_print(m_pdelay, this, buf);
}else{
// Send text to a single character with no colour parsing
process_moblog(this, buf);
if ( IS_NULLSTR(buf) || !this->desc){
return;
}
// convert < to <, > to > and & to &
buf=mxp_convert_to_mnemonics(buf);
// condensing system has to be flushed for raw colour to work correctly
flush_cached_write_to_buffer(this->desc);
if(this->desc->parse_colour){
this->desc->parse_colour=false;
write_to_buffer( this->desc, buf, 0);
flush_cached_write_to_buffer(this->desc);
this->desc->parse_colour=true;
}else{
write_to_buffer( this->desc, buf, 0);
flush_cached_write_to_buffer(this->desc);
}
}
}
/**************************************************************************/
// send b+w text + linefeed
void char_data::printlnbw(const char *buf)
{
printbw(buf);
print("\r\n");
}
/**************************************************************************/
// prepend \r\n to what is to be sent
void char_data::println(const char *buf)
{
print(buf);
print("\r\n");
}
/**************************************************************************/
void char_data::print_blank_lines(int lines)
{
char buf[MSL];
buf[0]='\0';
for(int i=0; i<lines; i++){
strcat(buf,"\r\n");
}
print(buf);
}
/**************************************************************************/
// prepend \r\n to what is to be sent
void char_data::println(int seconds, const char *buf)
{
if(!this){
return;
}
m_pdelay=seconds;
println(buf);
m_pdelay=0;
}
/**************************************************************************/
void char_data::printlnf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
println(temp_HSL_workspace);
}
/**************************************************************************/
void char_data::printlnfbw(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
printlnbw(temp_HSL_workspace);
}
/**************************************************************************/
void char_data::printlnf(int seconds, const char *fmt, ...)
{
if(!this){
return;
}
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
m_pdelay=seconds;
println(temp_HSL_workspace);
m_pdelay=0;
}
/**************************************************************************/
// wordwrap to the char
void char_data::wrap(const char *buf)
{
char *wrapped=str_dup(buf);
wrapped=note_format_string_width(wrapped, 77, true, false);
print(wrapped);
free_string(wrapped);
}
/**************************************************************************/
void char_data::wrapf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
char *wrapped=str_dup(temp_HSL_workspace);
wrapped=note_format_string_width(wrapped, 77, true, false);
print(wrapped);
free_string(wrapped);
}
/**************************************************************************/
// prepend \r\n to what is to be sent
void char_data::wrapln(const char *buf)
{
char *wrapped=str_dup(buf);
wrapped=note_format_string_width(wrapped, 77, true, true);
print(wrapped);
free_string(wrapped);
}
/**************************************************************************/
void char_data::wraplnf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(temp_HSL_workspace, HSL, fmt, args);
va_end(args);
char *wrapped=str_dup(temp_HSL_workspace);
wrapped=note_format_string_width(wrapped, 77, true, true);
print(wrapped);
free_string(wrapped);
}
/**************************************************************************/
int char_data::get_skill_level(int sn)
{
if (sn == -1 || sn>MAX_SKILL){
bugf("int char_data::get_skill_level(int sn), asking for sn=%d", sn);
return MAX_LEVEL;
}
return skill_table[sn].skill_level[clss];
}
/**************************************************************************/
// returns the percentage of skill they have in it
int char_data::get_skill(int sn)
{
// shorthand for level based skills
if (sn == -1){
return URANGE(0,(level * 5 / 2),100);
}
// bounds checking
if(sn < -1 || sn > MAX_SKILL){
bugf("char_data::get_skill(): Bad sn %d",sn);
return 0;
}
if(IS_NPC(this)){
return npc_skill_level(sn);
}
return pc_skill_level(sn);
}
/**************************************************************************/
int char_data::npc_skill_level(int sn)
{
if(IS_CONTROLLED(this)){
return 100;
}
int skill=0;
if (IS_SPELL(sn)){
skill= 40 + 2 * level;
}else{
if( sn==gsn_sneak||
sn==gsn_hide)
{
skill= level * 2 + 20;
}else if (sn==gsn_dodge){
if(IS_SET(off_flags,OFF_DODGE)){
skill = level * 2;
}
}else if(sn== gsn_parry){
if(IS_SET(off_flags,OFF_PARRY)){
skill = level * 2;
}
}else if(sn== gsn_shield_block){
skill=10 + 2 * level;
}else if(sn== gsn_second_attack){
if(IS_SET(act,ACT_WARRIOR | ACT_THIEF)){
skill = 10 + 3 * level;
}
}else if(sn== gsn_third_attack){
if(IS_SET(act,ACT_WARRIOR)){
skill = 4 * level - 40;
}
}else if(sn== gsn_quad_attack){
if(IS_SET(act,ACT_WARRIOR)){
skill = 5 * level - 60;
}
}else if(sn== gsn_hand_to_hand){
skill = 40 + 2 * level;
}else if(sn== gsn_trip){
if(IS_SET(off_flags,OFF_TRIP)){
skill = 10 + 3 * level;
}
}else if(sn== gsn_bash){
if(IS_SET(off_flags,OFF_BASH)){
skill = 10 + 3 * level;
}
}else if(sn== gsn_disarm){
if(IS_SET( off_flags,OFF_DISARM) &&
IS_SET(act,ACT_WARRIOR | ACT_THIEF))
{
skill = 20 + 3 * level;
}
}else if(sn== gsn_berserk){
if(IS_SET( off_flags,OFF_BERSERK)){
skill = 3 * level;
}
}else if(sn== gsn_kick){
skill = 10 + 3 * level;
}else if(sn== gsn_gore){
if(IS_SET( off_flags, OFF_GORE )){
skill = 10 + 3 * level;
}
}else if(sn== gsn_backstab){
if(IS_SET(act,ACT_THIEF)){
skill = 20 + 2 * level;
}
}else if(sn== gsn_rescue || sn== gsn_recall){
skill = 40 + level;
}else if(sn== gsn_sword
|| sn== gsn_spear
|| sn== gsn_dagger
|| sn== gsn_staff
|| sn== gsn_mace
|| sn== gsn_axe
|| sn== gsn_flail
|| sn== gsn_whip
|| sn== gsn_polearm)
{
skill = 40 + 5 * level / 2;
}else if (IS_SET(act2, ACT2_ALLSKILLS)){
skill = 40 + 2 * level;
}else{
skill = 0;
}
}
// dazed mobs
if (daze > 0)
{
if (IS_SPELL(sn)){
skill = 2 * skill / 3;
}else{
skill /= 2;
}
}
return URANGE(0,skill,100);
}
/**************************************************************************/
int char_data::pc_skill_level(int sn)
{
int skill;
// have level checks if it isnt a spell
if (!IS_SPELL(sn))
{
if (level < skill_table[sn].skill_level[clss]
|| skill_table[sn].skill_level[clss]==0)
skill = 0;
else
skill = pcdata->learned[sn];
}
else
{
skill = pcdata->learned[sn];
}
// grant working on skills and spells
if (pcdata->learned[sn]==101){
skill = 100;
}
// dazed players
if (daze > 0)
{
if (IS_SPELL(sn)){
skill = 2 * skill / 3;
}else{
skill /= 2;
}
}
// drunk players
if(pcdata->condition[COND_DRUNK]>10){
skill = 9 * skill / 10;
}
// scale down if using the new system
if(HAS_CONFIG(this,CONFIG_PRACSYS_TESTER)){
skill = skill * skill_table[sn].get_learnscale(this) / 100;
}
return URANGE(0,skill,100);
};
/**************************************************************************/
// return the percentage they have out of the max for the class
int char_data::get_display_skill(int sn)
{
if(IS_NPC(this)){
return this->get_skill(sn);
}
// bounds checking
if(sn < 0 || sn > MAX_SKILL){
bugf("char_data::get_display_skill(): Bad sn %d",sn);
return 0;
}
return (pcdata->learned[sn]);
};
/**************************************************************************/
void char_data::mpqueue_attached(time_t )
{
if(this){
this->mpqueue_count++;
}
};
/**************************************************************************/
/*
void char_data::mpqueue_removed(int when)
{
if(this){
this->mpqueue_count--;
}
};
*/
/**************************************************************************/
void mpqueue_dequeue_for(char_data *extracted_char);
/**************************************************************************/
// dequeue all the queued events involving us
void char_data::mpqueue_dequeue_all()
{
if(this && this->mpqueue_count>0){
mpqueue_dequeue_for(this);
}
};
/**************************************************************************/
vn_int char_data::vnum()
{
if(!this){
return -2; // NULL pointer
}
if(pIndexData){
return pIndexData->vnum; // mob vnum
}
return 0; // zero means it is a player
};
/**************************************************************************/
vn_int char_data::in_room_vnum()
{
if(!this || !in_room){
return 0; // zero means they arent in a room for some reason
}
return in_room->vnum; // room vnum
};
/**************************************************************************/
void char_data::sendpage(const char *buf)
{
char *txt=(char *)buf;
process_moblog(this, txt); // moblog flag
if ( IS_NULLSTR(txt) || !this || !desc){
return;
}
if (lines == 0 ) // pager turned off
{
print(txt);
return;
}
if (desc->showstr_head &&
(str_len(txt)+str_len(desc->showstr_head)+1) < 32000)
{
char *temp=(char*)alloc_mem(str_len(txt) + str_len(desc->showstr_head) + 1);
strcpy(temp, desc->showstr_head);
strcat(temp, txt);
desc->showstr_point = temp +
(desc->showstr_point - desc->showstr_head);
free_mem(desc->showstr_head, str_len(desc->showstr_head) + 1);
desc->showstr_head=temp;
}else{
if (desc->showstr_head){
free_mem(desc->showstr_head, str_len(desc->showstr_head)+1);
}
desc->showstr_head = (char*)alloc_mem(str_len(txt) + 1);
strcpy(desc->showstr_head,txt);
desc->showstr_point = desc->showstr_head;
show_string(desc,"");
}
}
/**************************************************************************/
void char_data::titlebar(const char *txt)
{
char *line= "=================================================================="
"==================================================================";
int clen=c_str_len(txt); // length of string without colour codes
// display a blank bar?
if(clen<1)
{
println("`#`=t-===========================================================================-`&");
return;
}
// to much text to display within a bar?
if(clen>78)
{
println(txt);
return;
}
char buf[MIL];
int spaces= (74-clen)/2;
if(clen%2==0){ // even
sprintf(buf, "`=t-%%.%ds`#`#`#`# `=T%%s `&`&`&`&%%.%ds-`x", spaces, spaces-1);
}else{ // odd
sprintf(buf, "`=t-%%.%ds`#`#`#`# `=T%%s `&`&`&`&%%.%ds-`x", spaces, spaces);
}
// show the titlebar
printlnf( buf, line, txt, line);
}
/**************************************************************************/
void char_data::titlebarf(const char *fmt, ...)
{
char buf[MIL];
va_list args;
va_start(args, fmt);
vsnprintf(buf, MIL, fmt, args);
va_end(args);
titlebar(buf);
}
/**************************************************************************/
void char_data::olctitlebar(const char *txt)
{
char *line= "=================================================================="
"==================================================================";
int clen=c_str_len(txt); // length of string without colour codes
// display a blank bar?
if(clen<1)
{
println("`#`=r-===========================================================================-`&");
return;
}
// to much text to display within a bar?
if(clen>78)
{
println(txt);
return;
}
char buf[MIL];
int spaces= (74-clen)/2;
if(clen%2==0){ // even
sprintf(buf, "`=r-%%.%ds`#`#`#`# `=R%%s `&`&`&`&%%.%ds-`x", spaces, spaces-1);
}else{ // odd
sprintf(buf, "`=r-%%.%ds`#`#`#`# `=R%%s `&`&`&`&%%.%ds-`x", spaces, spaces);
}
// show the titlebar
printlnf( buf, line, txt, line);
}
/**************************************************************************/
void char_data::olctitlebarf(const char *fmt, ...)
{
char buf[MIL];
va_list args;
va_start(args, fmt);
vsnprintf(buf, MIL, fmt, args);
va_end(args);
olctitlebar(buf);
}
/**************************************************************************/
extern const char *mxp_start; // defined in connect.h
/**************************************************************************/
void char_data::mxp_send_init()
{
// turning off or already off
if(!MXP_DETECTED_OR_ON(this)){
if(this){
if(pcdata){
pcdata->mxp_enabled=false;
}
if(desc){
desc->mxp_enabled=false;
}
print(MXP_LOCKED_MODE);
}
return;
}
// turning on
// send the mxp init stuff only once per hotreboot
if(!pcdata->mxp_enabled){
pcdata->mxp_enabled=true;
if(desc){
desc->mxp_enabled=true;
}
// this puts the client into secure mode
mxp_define_elements_to_char(this);
}
}
/**************************************************************************/
// send them the MXP enabled [Hit Return to continue] bar
void char_data::hit_return_to_continue()
{
print("`#`=\xaa");
print(mxp_create_send(this, "continue", "`c[Hit Return to continue]`x"));
println("`^");
}
/**************************************************************************/
// record says and emotes etc for display with the replayroom command
void char_data::record_replayroom_event(const char *txt)
{
char_data *ch=TRUE_CH(this);
if(!ch || !ch->pcdata){
// only record for players
return;
}
char recordbuf[MSL];
if(ch->pcdata->replayroom_lastevent_roomvnum!=in_room_vnum()){
// insert a blank line with a - for new rooms
sprintf(recordbuf, "-\r\n%s> %s", shorttime(NULL), txt);
ch->pcdata->replayroom_lastevent_roomvnum=in_room_vnum();
}else{
sprintf(recordbuf, "%s> %s", shorttime(NULL), txt);
}
replace_string( // record it in their replayroom buffer
ch->pcdata->replayroom_text[ch->pcdata->next_replayroom],
recordbuf);
++ch->pcdata->next_replayroom%=MAX_REPLAYROOM;
}
/**************************************************************************/
/**************************************************************************/