/**************************************************************************/ // 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", "[Hit Return to continue]")); 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; } /**************************************************************************/ /**************************************************************************/