// Oxxy (C) 2015, HPM plugin. #include #include #include #include "../common/HPMi.h" #include "../common/malloc.h" #include "../common/mmo.h" #include "../common/socket.h" #include "../common/strlib.h" #include "../common/timer.h" #include "../common/mapindex.h" #include "../map/clif.h" #include "../map/script.h" #include "../map/pc.h" #include "../map/atcommand.h" #include "../map/battle.h" #include "../map/map.h" #include "../map/log.h" #include "../map/channel.h" #include "../map/chat.h" #include "../map/skill.h" static char atcmd_output[CHAT_SIZE_MAX]; #include "../common/HPMDataCheck.h" /* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */ HPExport struct hplugin_info pinfo = { "Chat Color", // Plugin name SERVER_TYPE_MAP,// Which server types this plugin works with? "1.0", // Plugin version HPM_VERSION, // HPM Version (don't change, macro is automatically updated) }; BUILDIN(setcolor) { int color = script_getnum(st, 2); TBL_PC* sd; sd = script->rid2sd(st); pc_setglobalreg(sd, script->add_str("CHAT_COLOR"), color); return true; } ACMD(color) { int color; if(!message || !*message || (!sscanf(message, "%x", &color))) { clif->message(fd, "Usage: @color "); return false; } if (color > 0xFFFFFF || color < 0) color = 0; pc_setglobalreg(sd, script->add_str("CHAT_COLOR"), color); sprintf(atcmd_output,"Color has been set to %06X", color); clif->message(fd, atcmd_output); return true; } BUILDIN(color2hex) { int color = script_getnum(st, 2); char colorstring[7]; snprintf(colorstring, 7, "%06X", color); script_pushstrcopy(st, colorstring); return true; } void clif_parseGlobalMsg(int fd, struct map_session_data* sd) { const char* text = (char*)RFIFOP(fd,4); size_t textlen = RFIFOW(fd,2) - 4; char *name, *message, *fakename = NULL; size_t namelen, messagelen; bool is_fake; int color = pc->readregistry(sd,script->add_str("CHAT_COLOR")); // validate packet and retrieve name and message if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; if( atcommand->exec(fd, sd, message, true) ) return; if( !pc->can_talk(sd) ) return; if( battle->bc->min_chat_delay ) { //[Skotlex] if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) return; sd->cantalk_tick = timer->gettick() + battle->bc->min_chat_delay; } if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) { unsigned int next = pc->nextbaseexp(sd); if( next == 0 ) next = pc->thisbaseexp(sd); if( next ) { // 0%, 10%, 20%, ... int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); if( (battle->bc->snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0% switch (sd->state.snovice_call_flag) { case 0: if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?" sd->state.snovice_call_flag = 1; break; case 1: { char buf[256]; snprintf(buf, 256, msg_txt(1480), sd->status.name); if( strstr(message, buf) ) // "I am %s Super Novice~" sd->state.snovice_call_flag = 2; } break; case 2: if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T" sd->state.snovice_call_flag = 3; break; case 3: sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions sd->state.snovice_call_flag = 0; break; } } } } if( battle->bc->idletime_criteria & BCIDLE_CHAT ) sd->idletime = sockt->last_tick; if( sd->gcbind ) { channel->send(sd->gcbind,sd,message); return; } /** * Fake Name Design by FatalEror (bug report #9) **/ if( ( is_fake = ( sd->fakename[0] ) ) ) { fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3); strcpy(fakename, sd->fakename); strcat(fakename, " : "); strcat(fakename, message); textlen = strlen(fakename) + 1; } if(color && !sd->chatID) { char mout[200]; unsigned char mylen = 1; mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message); WFIFOHEAD(fd,mylen + 12); WFIFOW(fd,0) = 0x2C1; WFIFOW(fd,2) = mylen + 12; WFIFOL(fd,4) = sd->bl.id; WFIFOL(fd,8) = (color&0x0000FF) << 16 | (color&0x00FF00) | (color&0xFF0000) >> 16; // RGB -> BGR safestrncpy((char*)WFIFOP(fd,12), mout, mylen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); } else { // send message to others (using the send buffer for temp. storage) WFIFOHEAD(fd, 8 + textlen); WFIFOW(fd,0) = 0x8d; WFIFOW(fd,2) = 8 + textlen; WFIFOL(fd,4) = sd->bl.id; safestrncpy((char*)WFIFOP(fd,8), is_fake ? fakename : text, textlen); //FIXME: chat has range of 9 only clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); } // send back message to the speaker if( is_fake ) { WFIFOW(fd,0) = 0x8e; WFIFOW(fd,2) = textlen + 4; safestrncpy((char*)WFIFOP(fd,4), fakename, textlen); aFree(fakename); } else { memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); WFIFOW(fd,0) = 0x8e; } WFIFOSET(fd, WFIFOW(fd,2)); // Chat logging type 'O' / Global Chat logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); #ifdef PCRE_SUPPORT // trigger listening npcs map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); #endif } HPExport void plugin_init (void) { iMalloc = GET_SYMBOL("iMalloc"); script = GET_SYMBOL("script"); clif = GET_SYMBOL("clif"); pc = GET_SYMBOL("pc"); battle = GET_SYMBOL("battle"); timer = GET_SYMBOL("timer"); map = GET_SYMBOL("map"); logs = GET_SYMBOL("logs"); channel = GET_SYMBOL("channel"); atcommand = GET_SYMBOL("atcommand"); sockt = GET_SYMBOL("sockt"); chat = GET_SYMBOL("chat"); strlib = GET_SYMBOL("strlib"); session = GET_SYMBOL("session"); skill = GET_SYMBOL("skill"); mapindex = GET_SYMBOL("mapindex"); unit = GET_SYMBOL("unit"); addAtcommand("color", color); addScriptCommand("color2hex","i",color2hex); addScriptCommand("setcolor","i",setcolor); clif->pGlobalMessage = clif_parseGlobalMsg; } HPExport void server_online (void) { ShowInfo ("'%s' Plugin by Ancyker and Oxxy. Version '%s'\n",pinfo.name,pinfo.version); }