2022-03-05 12:44:06 +02:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "utils.h"
|
|
|
|
|
#include "char.h"
|
|
|
|
|
#include "char_manager.h"
|
|
|
|
|
#include "motion.h"
|
|
|
|
|
#include "packet.h"
|
|
|
|
|
#include "buffer_manager.h"
|
|
|
|
|
#include "unique_item.h"
|
|
|
|
|
#include "wedding.h"
|
|
|
|
|
|
|
|
|
|
#define NEED_TARGET (1 << 0)
|
|
|
|
|
#define NEED_PC (1 << 1)
|
|
|
|
|
#define WOMAN_ONLY (1 << 2)
|
|
|
|
|
#define OTHER_SEX_ONLY (1 << 3)
|
|
|
|
|
#define SELF_DISARM (1 << 4)
|
|
|
|
|
#define TARGET_DISARM (1 << 5)
|
|
|
|
|
#define BOTH_DISARM (SELF_DISARM | TARGET_DISARM)
|
|
|
|
|
|
|
|
|
|
struct emotion_type_s
|
|
|
|
|
{
|
|
|
|
|
const char * command;
|
|
|
|
|
const char * command_to_client;
|
2022-03-12 11:39:41 +02:00
|
|
|
|
int flag;
|
2022-03-05 12:44:06 +02:00
|
|
|
|
float extra_delay;
|
|
|
|
|
} emotion_types[] = {
|
|
|
|
|
{ "Ű<EFBFBD><EFBFBD>", "french_kiss", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, 2.0f },
|
|
|
|
|
{ "<EFBFBD>ǻ<EFBFBD>", "kiss", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, 1.5f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "slap", NEED_PC | SELF_DISARM, 1.5f },
|
|
|
|
|
{ "<EFBFBD>ڼ<EFBFBD>", "clap", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD>", "cheer1", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "cheer2", 0, 1.0f },
|
|
|
|
|
|
|
|
|
|
// DANCE
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1", "dance1", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>2", "dance2", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>3", "dance3", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>4", "dance4", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>5", "dance5", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>6", "dance6", 0, 1.0f },
|
|
|
|
|
// END_OF_DANCE
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "congratulation", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD>뼭", "forgive", 0, 1.0f },
|
|
|
|
|
{ "ȭ<EFBFBD><EFBFBD>", "angry", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD>Ȥ", "attractive", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "sad", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "shy", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "cheerup", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "banter", 0, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "joy", 0, 1.0f },
|
|
|
|
|
{ "\n", "\n", 0, 0.0f },
|
|
|
|
|
/*
|
|
|
|
|
//{ "Ű<><C5B0>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_FRENCH_KISS, 1.0f },
|
|
|
|
|
{ "<EFBFBD>ǻ<EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_KISS, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_SHORT_HUG, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_LONG_HUG, 1.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NEED_PC | SELF_DISARM, MOTION_ACTION_PUT_ARMS_SHOULDER, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD>¯", NEED_PC | WOMAN_ONLY | SELF_DISARM, MOTION_ACTION_FOLD_ARM, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NEED_PC | SELF_DISARM, MOTION_ACTION_SLAP, 1.5f },
|
|
|
|
|
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD>Ķ<EFBFBD>", 0, MOTION_ACTION_CHEER_01, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CHEER_02, 0.0f },
|
|
|
|
|
{ "<EFBFBD>ڼ<EFBFBD>", 0, MOTION_ACTION_CHEER_03, 0.0f },
|
|
|
|
|
|
|
|
|
|
{ "ȣȣ", 0, MOTION_ACTION_LAUGH_01, 0.0f },
|
|
|
|
|
{ "űű", 0, MOTION_ACTION_LAUGH_02, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_LAUGH_03, 0.0f },
|
|
|
|
|
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CRY_01, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CRY_02, 0.0f },
|
|
|
|
|
|
|
|
|
|
{ "<EFBFBD>λ<EFBFBD>", 0, MOTION_ACTION_GREETING_01, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_GREETING_02, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>", 0, MOTION_ACTION_GREETING_03, 0.0f },
|
|
|
|
|
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_INSULT_01, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", SELF_DISARM, MOTION_ACTION_INSULT_02, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_INSULT_03, 0.0f },
|
|
|
|
|
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_01, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_02, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_03, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_04, 0.0f },
|
|
|
|
|
{ "ơ", 0, MOTION_ACTION_ETC_05, 0.0f },
|
|
|
|
|
{ "<EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_06, 0.0f },
|
|
|
|
|
*/
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::set<std::pair<DWORD, DWORD> > s_emotion_set;
|
|
|
|
|
|
|
|
|
|
ACMD(do_emotion_allow)
|
|
|
|
|
{
|
|
|
|
|
if ( ch->GetArena() )
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>忡<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char arg1[256];
|
|
|
|
|
one_argument(argument, arg1, sizeof(arg1));
|
|
|
|
|
|
|
|
|
|
if (!*arg1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DWORD val = 0; str_to_number(val, arg1);
|
|
|
|
|
s_emotion_set.insert(std::make_pair(ch->GetVID(), val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CHARACTER_CanEmotion(CHARACTER& rch)
|
|
|
|
|
{
|
|
|
|
|
// <20><>ȥ<EFBFBD><C8A5> <20>ʿ<EFBFBD><CABF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
|
|
|
|
|
if (marriage::WeddingManager::instance().IsWeddingMap(rch.GetMapIndex()))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
|
|
|
|
|
if (rch.IsEquipUniqueItem(UNIQUE_ITEM_EMOTION_MASK))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (rch.IsEquipUniqueItem(UNIQUE_ITEM_EMOTION_MASK2))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ACMD(do_emotion)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
{
|
|
|
|
|
if (ch->IsRiding())
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ź <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; *emotion_types[i].command != '\n'; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp(cmd_info[cmd].command, emotion_types[i].command))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!strcmp(cmd_info[cmd].command, emotion_types[i].command_to_client))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*emotion_types[i].command == '\n')
|
|
|
|
|
{
|
|
|
|
|
sys_err("cannot find emotion");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CHARACTER_CanEmotion(*ch))
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_SET(emotion_types[i].flag, WOMAN_ONLY) && SEX_MALE==GET_SEX(ch))
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char arg1[256];
|
|
|
|
|
one_argument(argument, arg1, sizeof(arg1));
|
|
|
|
|
|
|
|
|
|
LPCHARACTER victim = NULL;
|
|
|
|
|
|
|
|
|
|
if (*arg1)
|
|
|
|
|
victim = ch->FindCharacterInView(arg1, IS_SET(emotion_types[i].flag, NEED_PC));
|
|
|
|
|
|
|
|
|
|
if (IS_SET(emotion_types[i].flag, NEED_TARGET | NEED_PC))
|
|
|
|
|
{
|
|
|
|
|
if (!victim)
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (victim)
|
|
|
|
|
{
|
|
|
|
|
if (!victim->IsPC() || victim == ch)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (victim->IsRiding())
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ź <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 11:39:41 +02:00
|
|
|
|
int distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
|
2022-03-05 12:44:06 +02:00
|
|
|
|
|
|
|
|
|
if (distance < 10)
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (distance > 500)
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ʹ<EFBFBD> <20>ָ<EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_SET(emotion_types[i].flag, OTHER_SEX_ONLY))
|
|
|
|
|
{
|
|
|
|
|
if (GET_SEX(ch)==GET_SEX(victim))
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_SET(emotion_types[i].flag, NEED_PC))
|
|
|
|
|
{
|
|
|
|
|
if (s_emotion_set.find(std::make_pair(victim->GetVID(), ch->GetVID())) == s_emotion_set.end())
|
|
|
|
|
{
|
|
|
|
|
if (true == marriage::CManager::instance().IsMarried( ch->GetPlayerID() ))
|
|
|
|
|
{
|
|
|
|
|
const marriage::TMarriage* marriageInfo = marriage::CManager::instance().Get( ch->GetPlayerID() );
|
|
|
|
|
|
|
|
|
|
const DWORD other = marriageInfo->GetOther( ch->GetPlayerID() );
|
|
|
|
|
|
|
|
|
|
if (0 == other || other != victim->GetPlayerID())
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20>ൿ<EFBFBD><E0B5BF> <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>մϴ<D5B4>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20>ൿ<EFBFBD><E0B5BF> <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>մϴ<D5B4>."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_emotion_set.insert(std::make_pair(ch->GetVID(), victim->GetVID()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char chatbuf[256+1];
|
|
|
|
|
int len = snprintf(chatbuf, sizeof(chatbuf), "%s %u %u",
|
|
|
|
|
emotion_types[i].command_to_client,
|
|
|
|
|
(DWORD) ch->GetVID(), victim ? (DWORD) victim->GetVID() : 0);
|
|
|
|
|
|
|
|
|
|
if (len < 0 || len >= (int) sizeof(chatbuf))
|
|
|
|
|
len = sizeof(chatbuf) - 1;
|
|
|
|
|
|
|
|
|
|
++len; // \0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
TPacketGCChat pack_chat;
|
|
|
|
|
pack_chat.header = HEADER_GC_CHAT;
|
|
|
|
|
pack_chat.size = sizeof(TPacketGCChat) + len;
|
|
|
|
|
pack_chat.type = CHAT_TYPE_COMMAND;
|
|
|
|
|
pack_chat.id = 0;
|
|
|
|
|
TEMP_BUFFER buf;
|
|
|
|
|
buf.write(&pack_chat, sizeof(TPacketGCChat));
|
|
|
|
|
buf.write(chatbuf, len);
|
|
|
|
|
|
|
|
|
|
ch->PacketAround(buf.read_peek(), buf.size());
|
|
|
|
|
|
|
|
|
|
if (victim)
|
|
|
|
|
sys_log(1, "ACTION: %s TO %s", emotion_types[i].command, victim->GetName());
|
|
|
|
|
else
|
|
|
|
|
sys_log(1, "ACTION: %s", emotion_types[i].command);
|
|
|
|
|
}
|
|
|
|
|
|