MikZ 5 Posted May 14, 2018 (edited) Good day! Help me how to correct these warnings please. Spoiler /* * This file is part of a Hercules Plugin library. * http://herc.ws - http://github.com/HerculesWS/Hercules * __ _ * / _\_ __ ___ ___ | | _______ ___ _ ____ * \ \| '_ ` _ \ / _ \| |/ / _ \ \/ / | | |_ / * _\ \ | | | | | (_) | < __/> <| |_| |/ / * \__/_| |_| |_|\___/|_|\_\___/_/\_\\__, /___| * |___/ * * Copyright (c) 2017 Smokexyz ([email protected]) * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License <http://www.gnu.org/licenses/> for * more details. * * * * * * * * * * * * * * * * * * * * * * * * * * Hercules Battlegrounds Plugin by [Smokexyz] * * * * * * * * * * * * * * * * * * * * * * * * */ #include "common/hercules.h" /* Should always be the first Hercules file included! */ #include "common/memmgr.h" #include "common/mmo.h" #include "common/socket.h" #include "common/strlib.h" #include "common/nullpo.h" #include "common/timer.h" #include "common/utils.h" #include "common/sql.h" #include "map/chrif.h" #include "map/atcommand.h" #include "map/clif.h" #include "map/pc.h" #include "map/script.h" #include "map/npc.h" #include "map/party.h" #include "map/mapreg.h" #include "map/guild.h" #include "map/chat.h" #include "map/quest.h" #include "map/mob.h" #include "map/map.h" #include "map/pet.h" #include "map/homunculus.h" #include "map/mercenary.h" #include "map/elemental.h" #include "map/skill.h" #include "map/battleground.h" #include "char/mapif.h" #include "char/inter.h" #include "plugins/HPMHooking.h" /* Hooking Macros */ #include "common/HPMDataCheck.h" /* should always be the last Hercules file included! */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Utility Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define add2limit(a, b, max) \ do { \ if ((max - a) < b) { \ a = max; \ } else { \ a += b; \ } \ } while(0) #define sub2limit(a, b, min) \ do { \ if ((b + min) > a) { \ a = min; \ } else { \ a -= b; \ } \ } while(0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * HPM Structure Definition * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ HPExport struct hplugin_info pinfo = { "Hercules Battlegrounds", // Plugin name SERVER_TYPE_MAP | SERVER_TYPE_CHAR, // Server Type "1.0a", // Plugin version HPM_VERSION, // HPM Version (automatically updated) }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Global Variables * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define MAX_BATTLEGROUND_TEAMS 13 #define BLUE_SKULL 8965 #define RED_SKULL 8966 #define GREEN_SKULL 8967 /* Queue Database */ static struct DBMap* hBG_queue_db; /* Battleground Guild Storage */ struct guild bg_guild[MAX_BATTLEGROUND_TEAMS]; /* Battleground Guild Colors */ const unsigned int bg_colors[MAX_BATTLEGROUND_TEAMS] = { 0x0000FF, // Blue 0xFF0000, // Red 0x00FF00, // Green 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF }; /* Counter to check the next battleground ID */ static unsigned int bg_team_counter = 0; /* hBG Queue Counter */ static unsigned int hBG_queue_counter = 0; /** * Battle Configuration Variables */ int hBG_idle_announce, hBG_idle_autokick, hBG_reward_rates, hBG_ranked_mode, hBG_reportafk_leaderonly, hBG_balanced_queue, hBG_ip_check, hBG_from_town_only, hBG_enabled, hBG_xy_interval, hBG_leader_change; /** * BG Fame list types */ enum bg_fame_list_types { BG_NORMAL, BG_RANKED }; /** * Inter-server communication packet IDs. */ enum inter_packet_types { PACKET_INTER_BG_STATS_SAVE = 0x9000, PACKET_INTER_BG_STATS_REQ, PACKET_MAP_BG_STATS_GET, }; enum bg_mob_types { BARRICADE_ = 1906, OBJ_NEUTRAL = 1911, E_BAPHOMET2 = 2100, E_LORD_OF_DEATH2, E_DARK_LORD, E_KTULLANUX, E_DARK_SNAKE_LORD, E_TURTLE_GENERAL, E_APOCALIPS_H, E_FALLINGBISHOP, }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Structure Definitions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * BGD Structure Appendant */ struct hBG_data { time_t created_at; // Creation of this Team int leader_char_id; unsigned int color; // BG Guild Link struct guild *g; bool reveal_pos, reveal_pos2, reveal_flag; // Score Board int team_score; }; /** * hBG Queue Member Linked List */ struct hBG_queue_member { int position; struct map_session_data *sd; struct hBG_queue_member *next; }; struct hBG_stats { unsigned int best_damage, boss_damage, total_damage_done, total_damage_received; unsigned short // Triple Inferno ti_wins, ti_lost, ti_tie, // Tierra EoS eos_flags, eos_bases, eos_wins, eos_lost, eos_tie, // Tierra Bossnia boss_killed, boss_flags, boss_wins, boss_lost, boss_tie, // Tierra Domination dom_bases, dom_off_kills, dom_def_kills, dom_wins, dom_lost, dom_tie, // Flavius TD td_kills, td_deaths, td_wins, td_lost, td_tie, // Flavius SC sc_stolen, sc_captured, sc_dropped, sc_wins, sc_lost, sc_tie, // Flavius CTF ctf_taken, ctf_captured, ctf_dropped, ctf_wins, ctf_lost, ctf_tie, // Conquest emperium_kills, barricade_kills, guardian_stone_kills, conquest_wins, conquest_losses, // Rush ru_captures, ru_wins, ru_lost, ru_skulls; unsigned int // Ammo sp_heal_potions, hp_heal_potions, yellow_gemstones, red_gemstones, blue_gemstones, poison_bottles, acid_demostration, acid_demostration_fail, support_skills_used, healing_done, wrong_support_skills_used, wrong_healing_done, sp_used, zeny_used, spiritb_used, ammo_used; unsigned short kill_count, death_count, wins, losses, ties, wins_as_leader, losses_as_leader, ties_as_leader, total_deserted, ranked_games; int score, points, ranked_points; }; /** * MSD Structure Appendant (class 0) */ struct hBG_queue_data { unsigned int q_id, users, min_level; struct hBG_queue_member *first, *last; char queue_name[50], join_event[EVENT_NAME_LENGTH]; }; /** * MSD Structure Appendant (class 1) */ struct hBG_map_session_data { unsigned int bg_kills; struct { unsigned afk : 1; } state; struct hBG_stats stats; }; /** * MOBD Structure Appendant */ struct hBG_mob_data { struct { unsigned immunity: 1; } state; }; /** * MAPD Structure Appendant */ struct hBG_mapflag { unsigned hBG_topscore : 1; // No Detect NoMapFlag }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Function Forward Declarations * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int hBG_countlogin(struct map_session_data *sd, bool check_bat_room); int hBG_config_get(const char *key); struct guild* hBG_get_guild(int bg_id); struct map_session_data* hBG_getavailablesd(struct battleground_data *bgd); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Packet Sending Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Updates HP bar of a camp member. * Packet Ver < 20140613: 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W (ZC_BATTLEFIELD_NOTIFY_HP). * Packet Ver >= 20140613: 0a0e <account id>.L <hp>.L <max hp>.L (ZC_BATTLEFIELD_NOTIFY_HP2) * * @param sd map_session_data to send the packet to. * @return void. */ void hBG_send_hp_area(struct map_session_data *sd) { unsigned char buf[34]; // packet version can be wrong, // due to inconsistend data on other servers. #if PACKETVER < 20140613 const int cmd = 0x2e0; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->status.account_id; memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH); if (sd->battle_status.max_hp > INT16_MAX) { // To correctly display the %hp bar. [Skotlex] WBUFW(buf, 30) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); WBUFW(buf, 32) = 100; } else { WBUFW(buf, 30) = sd->battle_status.hp; WBUFW(buf, 32) = sd->battle_status.max_hp; } clif->send(buf, packet->len, &sd->bl, BG_AREA_WOS); #else const int cmd = 0xa0e; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->status.account_id; if (sd->battle_status.max_hp > INT32_MAX) { WBUFL(buf, 6) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); WBUFL(buf, 10) = 100; } else { WBUFL(buf, 6) = sd->battle_status.hp; WBUFL(buf, 10) = sd->battle_status.max_hp; } clif->send(buf, packet->len, &sd->bl, BG_AREA_WOS); #endif } /** * Notify a singly client of HP change. * * @param fd socket fd to write * @param sd map_session_data containing information to be sent. */ void hBG_send_hp_single(int fd, struct map_session_data* sd) { const int cmd = 0x2e0; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WFIFOHEAD(fd, packet->len); WFIFOW(fd, 0) = cmd; WFIFOL(fd, 2) = sd->bl.id; memcpy(WFIFOP(fd,6),sd->status.name, NAME_LENGTH); if (sd->battle_status.max_hp > INT16_MAX) { WFIFOW(fd, 30) = sd->battle_status.hp/(sd->battle_status.max_hp/100); WFIFOW(fd, 32) = 100; } else { WFIFOW(fd, 30) = sd->battle_status.hp; WFIFOW(fd, 32) = sd->battle_status.max_hp; } WFIFOSET(fd, packet->len); } /** * Character Guild Name Information Packet * * @param sd map_session_data to send the packet to. * @return void */ void hBG_send_guild_info(struct map_session_data *sd) { int fd; int cmd = 0x16c; struct guild *g; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (!sd->bg_id || (g = hBG_get_guild(sd->bg_id)) == NULL || packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = 0x16c; WFIFOL(fd,2) = g->guild_id; WFIFOL(fd,6) = g->emblem_id; WFIFOL(fd,10) = 0; WFIFOB(fd,14) = 0; WFIFOL(fd,15) = 0; memcpy(WFIFOP(fd,19), g->name, NAME_LENGTH); WFIFOSET(fd, packet->len); } /** * Sends guild skills (ZC_GUILD_SKILLINFO). * 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B }* */ void hBG_send_guild_skillinfo(struct map_session_data* sd) { int fd; struct guild* g; int i,c; nullpo_retv(sd); if (!sd->bg_id || (g = hBG_get_guild(sd->bg_id)) == NULL) return; fd = sd->fd; WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37); WFIFOW(fd,0) = 0x0162; WFIFOW(fd,4) = g->skill_point; for (i = 0, c = 0; i < MAX_GUILDSKILL; i++) { if(g->skill[i].id > 0 && guild->check_skill_require(g, g->skill[i].id)) { int id = g->skill[i].id; int p = 6 + c*37; WFIFOW(fd,p+0) = id; WFIFOL(fd,p+2) = skill->get_inf(id); WFIFOW(fd,p+6) = g->skill[i].lv; if ( g->skill[i].lv) { WFIFOW(fd, p + 8) = skill->get_sp(id, g->skill[i].lv); WFIFOW(fd, p + 10) = skill->get_range(id, g->skill[i].lv); } else { WFIFOW(fd, p + 8) = 0; WFIFOW(fd, p + 10) = 0; } safestrncpy(WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; } } WFIFOW(fd,2) = 6 + c*37; WFIFOSET(fd,WFIFOW(fd,2)); } /** * Sends Guild Window Information * 01b6 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B <zeny>.L (ZC_GUILD_INFO2) * @param sd map_session_data to send the packet to. * @return void */ void hBG_guild_window_info(struct map_session_data *sd) { int fd; int cmd = 0x1b6; struct guild *g; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); fd = sd->fd; if ((g = hBG_get_guild(sd->bg_id)) == NULL || packet == NULL) return; WFIFOHEAD(fd, packet->len); // Hardcoded Length WFIFOW(fd, 0)= cmd; WFIFOL(fd, 2)= g->guild_id; WFIFOL(fd, 6)= g->guild_lv; WFIFOL(fd,10)= g->connect_member; WFIFOL(fd,14)= g->max_member; WFIFOL(fd,18)= g->average_lv; WFIFOL(fd,22)= (uint32)cap_value(g->exp,0,INT32_MAX); WFIFOL(fd,26)= g->next_exp; WFIFOL(fd,30)= 0; // Tax Points WFIFOL(fd,34)= 0; // Honor: (left) Vulgar [-100,100] Famed (right) WFIFOL(fd,38)= 0; // Virtue: (down) Wicked [-100,100] Righteous (up) WFIFOL(fd,42)= g->emblem_id; memcpy(WFIFOP(fd,46), g->name, NAME_LENGTH); memcpy(WFIFOP(fd,70), g->master, NAME_LENGTH); //safestrncpy(WFIFOP(fd,94), 0, 0); // "'N' castles" WFIFOL(fd, 110) = 0; // zeny WFIFOSET(fd, packet->len); } /** * Sends Guild Emblem to a player * @param sd map_session_data to send the packet to * @param g guild data * @return void */ void hBG_send_emblem(struct map_session_data *sd, struct guild *g) { int fd; nullpo_retv(sd); nullpo_retv(g); if (g->emblem_len <= 0) return; fd = sd->fd; WFIFOHEAD(fd, g->emblem_len+12); WFIFOW(fd,0) = 0x152; WFIFOW(fd,2) = g->emblem_len+12; WFIFOL(fd,4) = g->guild_id; WFIFOL(fd,8) = g->emblem_id; memcpy(WFIFOP(fd,12),g->emblem_data,g->emblem_len); WFIFOSET(fd, WFIFOW(fd,2)); } /** * Sends guild member list * @param sd map_session_data to send the packet to * @return void */ void hBG_send_guild_member_list(struct map_session_data *sd) { int fd, i, c; struct battleground_data *bgd; struct map_session_data *psd; struct hBG_data *hBGd; nullpo_retv(sd); if ((fd = sd->fd) == 0) return; if (!sd->bg_id || (bgd = bg->team_search(sd->bg_id)) == NULL) return; else if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return; WFIFOHEAD(fd, bgd->count * 104 + 4); WFIFOW(fd, 0) = 0x154; for (i = 0, c = 0; i < bgd->count; i++) { struct hBG_map_session_data *hBGsd; if ((psd = bgd->members[i].sd) == NULL) continue; if ((hBGsd = getFromMSD(psd, 1)) == NULL) continue; WFIFOL(fd,c*104+ 4) = psd->status.account_id; WFIFOL(fd,c*104+ 8) = psd->status.char_id; WFIFOW(fd,c*104+12) = psd->status.hair; WFIFOW(fd,c*104+14) = psd->status.hair_color; WFIFOW(fd,c*104+16) = psd->status.sex; WFIFOW(fd,c*104+18) = psd->status.class; WFIFOW(fd,c*104+20) = psd->status.base_level; WFIFOL(fd,c*104+22) = hBGsd->bg_kills; // Exp slot used to show kills WFIFOL(fd,c*104+26) = 1; // Online WFIFOL(fd,c*104+30) = hBGd->leader_char_id == psd->status.char_id ? 0 : 1; // Position memset(WFIFOP(fd,c*104+34),0,50); // Position Name memcpy(WFIFOP(fd,c*104+84),psd->status.name,NAME_LENGTH); // Player Name c++; } WFIFOW(fd, 2)=c*104+4; WFIFOSET(fd,WFIFOW(fd,2)); } /** * Send guild leave packet * @param sd map_session_data to send the packet to * @param *name contains name of the character. * @param *mes contains leave message from player. * @return void */ void hBG_send_leave_single(struct map_session_data *sd, const char *name, const char *mes) { unsigned char buf[128]; int cmd = 0x15a; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; memcpy(WBUFP(buf, 2), name, NAME_LENGTH); memcpy(WBUFP(buf,26), mes, 40); clif->send(buf, packet->len, &sd->bl, SELF); } /** * Notifies clients of a battleground message ZC_BATTLEFIELD_CHAT * 02dc <packet len>.W <account id>.L <name>.24B <message>.?B * * @param bgd battleground_data to send the message to * @param src_id id of the source of the message. * @param name contains the name of the character. * @param mes contains the message to be sent. * @param len contains the length of the message. * @return void. */ void hBG_send_chat_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, int len) { struct map_session_data *sd; unsigned char *buf; nullpo_retv(bgd); nullpo_retv(name); nullpo_retv(mes); if ((sd = hBG_getavailablesd(bgd)) == NULL) return; len = (int)strlen(mes); Assert_retv(len <= INT16_MAX - NAME_LENGTH - 8); buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char)); WBUFW(buf, 0) = 0x2dc; WBUFW(buf, 2) = len + NAME_LENGTH + 8; WBUFL(buf, 4) = src_id; memcpy(WBUFP(buf, 8), name, NAME_LENGTH); memcpy(WBUFP(buf, 32), mes, len); // [!] no NULL terminator clif->send(buf, WBUFW(buf, 2), &sd->bl, BG); if (buf) aFree(buf); } /** * Notifies the client of a guild expulsion. * * @param sd map_session_data to send the packet to * @param *name contains the name of the character. * @param *mes contains the expulsion message. */ void hBG_send_expulsion(struct map_session_data *sd, const char *name, const char *mes) { int fd; int cmd = 0x15c; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = cmd; safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); safestrncpy((char*)WFIFOP(fd,26), mes, 40); safestrncpy((char*)WFIFOP(fd,66), "", NAME_LENGTH); WFIFOSET(fd, packet->len); } /** * Notifies a single client of BG score updates * * @param sd map_session_data to send the packet to * @return void */ void hBG_update_score_single(struct map_session_data *sd) { int fd; int cmd = 0x2de; struct battleground_data *bgd; struct hBG_data *hBGd; struct hBG_mapflag *hBG_mf = getFromMAPD(&map->list[sd->bl.m], 0); const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = cmd; if (map->list[sd->bl.m].flag.battleground == 2) { // Score Board on Map. Team vs Team WFIFOW(fd,2) = map->list[sd->bl.m].bgscore_lion; WFIFOW(fd,4) = map->list[sd->bl.m].bgscore_eagle; } else if (map->list[sd->bl.m].flag.battleground == 3 && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) { // Score Board Multiple. Team vs Best Score WFIFOW(fd,2) = hBGd->team_score; WFIFOL(fd,4) = hBG_mf->hBG_topscore; } WFIFOSET(fd, packet->len); } /** * Notifies all clients in a Battleground Team * * @param bgd battleground_data containing the map_session_datas to send the packet to * @return void */ void hBG_update_score_team(struct battleground_data *bgd) { unsigned char buf[6]; struct map_session_data *sd; int i, m, cmd = 0x2de; struct hBG_data *hBGd = getFromBGDATA(bgd, 0); struct hBG_mapflag *hBG_mf; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(bg); if ((m = map->mapindex2mapid(bgd->mapindex)) < 0 || hBGd == NULL || (hBG_mf = getFromMAPD(&map->list[m], 0)) == NULL || packet == NULL) return; WBUFW(buf,0) = cmd; WBUFW(buf,2) = hBGd->team_score; WBUFW(buf,4) = hBG_mf->hBG_topscore; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL || sd->bl.m != m) continue; clif->send(buf, packet->len, &sd->bl, SELF); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Queue System Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Searches hBG_queue_db by q_id * @param q_id contains the id of the queue to be searched. * @return hBG_queue_data * pointer to the memory location or null if not found. */ struct hBG_queue_data* hBG_queue_search(int q_id) { // Search a Queue using q_id if (!q_id) return NULL; return (struct hBG_queue_data *) idb_get(hBG_queue_db, q_id); } /** * Creates a Queue * @param queue_name contains the name of the queue. * @param join_event contains the event run on joining the queue. * @param min_level contains the minimum level to be able to join. * @return queue_id id of the queue created. */ int hBG_queue_create(const char* queue_name, const char* join_event, int min_level) { struct hBG_queue_data *hBGqd; if (++hBG_queue_counter <= 0) hBG_queue_counter = 1; CREATE(hBGqd, struct hBG_queue_data, 1); hBGqd->q_id = hBG_queue_counter; safestrncpy(hBGqd->queue_name, queue_name, sizeof(hBGqd->queue_name)); safestrncpy(hBGqd->join_event, join_event, sizeof(hBGqd->join_event)); hBGqd->first = hBGqd->last = NULL; // First and Last Queue Members hBGqd->users = 0; hBGqd->min_level = min_level; idb_put(hBG_queue_db, hBG_queue_counter, hBGqd); return hBGqd->q_id; } /** * Remove all queue members from the queue and free the links. * @param hBGqd pointer to the queue data. * @return void. */ void hBG_queue_members_finalize(struct hBG_queue_data *hBGqd) { struct hBG_queue_member *head, *next; nullpo_retv(hBGqd); head = hBGqd->first; while (head) { next = head->next; aFree(head); head = next; } hBGqd->first = hBGqd->last = NULL; hBGqd->users = 0; } /** * Add a player to the queue. * @param hBGqd pointer to the queue data. * @param sd player to be added to the queue. * @return postition of the player in queue. */ int hBG_queue_member_add(struct hBG_queue_data *hBGqd, struct map_session_data *sd) { struct hBG_queue_member *hBGqm; nullpo_retr(0, hBGqd); nullpo_retr(0, sd); hBGqd->users++; CREATE(hBGqm, struct hBG_queue_member, 1); hBGqm->sd = sd; hBGqm->position = hBGqd->users; hBGqm->next = NULL; if (getFromMSD (sd, 0) == NULL) addToMSD(sd, hBGqd, 0, false); if (hBGqd->last == NULL) { hBGqd->first = hBGqd->last = hBGqm; // Attach to first position } else { // Attach at the end of the queue hBGqd->last->next = hBGqm; hBGqd->last = hBGqm; } return hBGqm->position; } /** * Get a member of the queue from position n. * @param hBGqd pointer to the queue data * @param position position of the player in queue * @return queue_member data or NULL if not found. */ struct hBG_queue_member* hBG_queue_member_get(struct hBG_queue_data *hBGqd, int position) { struct hBG_queue_member *head; if (!hBGqd) return NULL; head = hBGqd->first; while (head != NULL) { if (head->sd && head->position == position) return head; head = head->next; } return NULL; } /** * Clear a queue and remove from memory. * @param hBGqd pointer to queue_data * return 1 on success, 0 on failure. */ int hBG_queue_destroy(struct hBG_queue_data *hBGqd) { nullpo_ret(hBGqd); hBG_queue_members_finalize(hBGqd); idb_remove(hBG_queue_db, hBGqd->q_id); return 1; } /** * Remove a member from a queue * @param hBGqd pointer to queue data. * @param id block list ID of player in queue. * @return position of a player in the queue or 0 if not found. */ int hBG_queue_member_remove(struct hBG_queue_data *hBGqd, int id) { struct hBG_queue_member *head, *previous; int i; nullpo_retr(0, hBGqd); head = hBGqd->first; previous = NULL; while (head != NULL) { if (head->sd && head->sd->bl.id == id) { struct hBG_queue_member *next; next = head->next; i = head->position; hBGqd->users--; // De-attach target from the main queue if (previous) { previous->next = head->next; } else { hBGqd->first = head->next; // Deleted is on first position } if (head->next == NULL) hBGqd->last = previous; // Deleted is on last position while (next != NULL) { next->position--; // Decrement positions of the next in queue. next = next->next; } aFree(head); return i; } previous = head; head = head->next; } return 0; } /** * Search a member in the queue by Block List ID. * @param hBGqd pointer to queue data. * @param id block list ID of a player in queue. * @return position of a player in the queue or 0 if not found. */ int hBG_queue_member_search(struct hBG_queue_data *hBGqd, int id) { struct hBG_queue_member *head; nullpo_retr(0,hBGqd); head = hBGqd->first; while (head != NULL) { if (head->sd && head->sd->bl.id == id) return head->position; head = head->next; } return 0; // Not Found } /** * Add a player to the queue. * @param sd pointer to player to be added in queue. * @param q_id ID of the queue to be appended. * @return 0 on failure, 1 on success. */ int hBG_queue_join(struct map_session_data *sd, int q_id) { char output[128]; struct hBG_queue_data *hBGqd; int i = 0; int login_ip_count = hBG_config_get("battle_configuration/hBG_ip_check"); nullpo_ret(sd); if (hBG_config_get("battle_configuration/hBG_from_town_only") && map->list[sd->bl.m].flag.town == 0) { clif->message(sd->fd,"You only can join BG queues from Towns or BG Waiting Room."); return 0; } else if (sd->bg_id) { clif->message(sd->fd,"You cannot join queues when already playing Battlegrounds."); return 0; } else if (sd->sc.data[SC_JAILED]) { clif->message(sd->fd,"You cannot join queues when jailed."); return 0; } // Get Queue by ID if ((hBGqd = hBG_queue_search(q_id)) == NULL) { return 0; // Current Queue don't exists } else if ((i = hBG_queue_member_search(hBGqd, sd->bl.id))) { // You cannot join a Queue if you are already in one. sprintf(output, "You are already in %s queue at position %d.", hBGqd->queue_name, i); clif->message(sd->fd, output); return 0; } else if (hBGqd && hBGqd->min_level && sd->status.base_level < hBGqd->min_level) { sprintf(output,"You cannot join %s queue. Required min level is %ud.", hBGqd->queue_name, hBGqd->min_level); clif->message(sd->fd,output); return 0; } else if (login_ip_count && hBG_countlogin(sd,false) > login_ip_count) { sprintf(output,"You cannot join %s queue. A max of %d characters are using your IP address.", hBGqd->queue_name, login_ip_count); clif->message(sd->fd,output); return 0; } i = hBG_queue_member_add(hBGqd, sd); sprintf(output,"You have joined %s queue at position %d.", hBGqd->queue_name, i); clif->message(sd->fd,output); if (hBGqd->join_event[0]) npc->event_do(hBGqd->join_event); return i; } /** * Process player leaving a queue. * @param sd pointer to player leaving the queue. * @param q_id ID of the queue to be left. * @return 0 on failure, 1 on success. */ int hBG_queue_leave(struct map_session_data *sd, int q_id) { char output[128]; struct hBG_queue_data *qd; if ((qd = hBG_queue_search(q_id)) == NULL) return 0; if (!hBG_queue_member_remove(qd,sd->bl.id)) { sprintf(output,"You are not in the %s queue.", qd->queue_name); clif->message(sd->fd,output); return 0; } sprintf(output, "You have been removed from the %s queue.", qd->queue_name); clif->message(sd->fd, output); return 1; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Battleground Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Return any available player in a Battleground * @param bgd pointer to battleground queue. * @return map_session_data *sd pointer to player data or NULL if not found. */ struct map_session_data* hBG_getavailablesd(struct battleground_data *bgd) { int i; nullpo_retr(NULL, bgd); ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd != NULL); return(i < MAX_BG_MEMBERS) ? bgd->members[i].sd : NULL; } /** * Count the number of players with the same IP in battlegrounds. * @param sd pointer to map session data. * @param check_bat_room boolean to include checks in bat_room. * @return amount of accounts online. */ int hBG_countlogin(struct map_session_data *sd, bool check_bat_room) { int c = 0, m = map->mapname2mapid("bat_room"); struct map_session_data* pl_sd; struct s_mapiterator* iter; nullpo_ret(sd); iter = mapit_getallusers(); for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) { if (!(getFromMSD(sd, 0) || map->list[pl_sd->bl.m].flag.battleground || (check_bat_room && pl_sd->bl.m == m))) continue; if (sockt->session[sd->fd]->client_addr == sockt->session[pl_sd->fd]->client_addr) c++; } mapit->free(iter); return c; } /** * Performs initialization tasks on new battlegrounds. * @param m map Index * @param rx respawn X co-ordinate * @param ry respawn Y co-ordinate * @param guild_index Index of the BG guild to be used * @param *ev NPC Script event to be called when player logs out. * @param *dev NPC Script event to be called when player dies. * @return ID of the battleground. */ int hBG_create(unsigned short m, short rx, short ry, int guild_index, const char *ev, const char *dev) { struct battleground_data *bgd; struct hBG_data *hBGd; CREATE(bgd, struct battleground_data, 1); CREATE(hBGd, struct hBG_data, 1); if (++bg_team_counter <= 0) bg_team_counter = 1; bgd->bg_id = bg_team_counter; bgd->count = 0; bgd->mapindex = m; bgd->x = rx; bgd->y = ry; safestrncpy(bgd->logout_event, ev, sizeof(bgd->logout_event)); safestrncpy(bgd->die_event, dev, sizeof(bgd->die_event)); memset(&bgd->members, 0, sizeof(bgd->members)); hBGd->color = bg_colors[guild_index]; hBGd->created_at = 0; hBGd->g = &bg_guild[guild_index]; addToBGDATA(bgd, hBGd, 0, true); idb_put(bg->team_db, bg_team_counter, bgd); return bgd->bg_id; } /** * Add a player to the Battleground Team * @param bg_id Id of the battleground * @param sd pointer to the player's session data. * @return 0 on failure, 1 on success. */ int hBG_team_join(int bg_id, struct map_session_data *sd) { // Player joins team int i; struct battleground_data *bgd = bg->team_search(bg_id); struct map_session_data *pl_sd; struct hBG_map_session_data *hBGsd; struct hBG_data *hBGd; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL || sd == NULL || sd->bg_id) return 0; ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == NULL); if (i == MAX_BG_MEMBERS) return 0; // No free slots // Handle Additional Map Session BG data if ((hBGsd = getFromMSD(sd, 1)) == NULL) { CREATE(hBGsd, struct hBG_map_session_data, 1); addToMSD(sd, hBGsd, 1, false); } hBGsd->bg_kills = 0; hBGsd->state.afk = 0; // Update player's idle item. pc->update_idle_time(sd, BCIDLE_WALK); sd->bg_id = bg_id; // Battleground Member data bgd->members[i].sd = sd; bgd->members[i].x = sd->bl.x; bgd->members[i].y = sd->bl.y; bgd->count++; // Guild Member Data simulation hBGd->g->member[i].sd = sd; // Creation Tick = First member joined. if (hBGd->created_at == 0) hBGd->created_at = sockt->last_tick; // First Join = Team Leader if (hBGd->leader_char_id == 0) hBGd->leader_char_id = sd->status.char_id; guild->send_dot_remove(sd); hBG_send_guild_info(sd); // Send Guild Name/Emblem under character clif->charnameupdate(sd); // Update character's nameplate for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((pl_sd = bgd->members[i].sd) == NULL) continue; // Simulate Guild Information hBG_guild_window_info(pl_sd); // Main Guild window information. hBG_send_emblem(pl_sd, hBGd->g); // Emblems hBG_send_guild_member_list(pl_sd); // Member list hBG_send_guild_skillinfo(sd); // Send Guild skill information. if (pl_sd != sd) hBG_send_hp_single(sd->fd,pl_sd); } clif->guild_emblem_area(&sd->bl); clif->bg_hp(sd); clif->bg_xy(sd); return 1; } /** * Reveal a player's position to another player. * @param bl pointer to block list. * @param ap list of arguments * @return 0. */ int hBG_reveal_pos(struct block_list *bl, va_list ap) { struct map_session_data *pl_sd, *sd = NULL; int flag, color; pl_sd = (struct map_session_data *)bl; sd = va_arg(ap,struct map_session_data *); // Source flag = va_arg(ap,int); color = va_arg(ap,int); if (pl_sd->bg_id == sd->bg_id) return 0; // Same Team clif->viewpoint(pl_sd,sd->bl.id,flag,sd->bl.x,sd->bl.y,sd->bl.id,color); return 0; } /** * Remove minimap indicator for player. * @param sd pointer to session data. * @return 0 */ int hBG_send_dot_remove(struct map_session_data *sd) { struct battleground_data *bgd; struct hBG_data *hBGd; int m; if (sd && sd->bg_id && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) { clif->bg_xy_remove(sd); if (hBGd->reveal_pos && (m = map->mapindex2mapid(bgd->mapindex)) == sd->bl.m) map->foreachinmap(hBG_reveal_pos, m,BL_PC,sd,2,0xFFFFFF); } return 0; } /** * Searches and removes battleground game specific * items from the player's inventory. * @param sd as struct map_session_data */ void hBG_member_remove_bg_items(struct map_session_data *sd) { int n; nullpo_retv(sd); if ((n = pc->search_inventory(sd,BLUE_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2, LOG_TYPE_CONSUME); if ((n = pc->search_inventory(sd,RED_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2,LOG_TYPE_CONSUME); if ((n = pc->search_inventory(sd,GREEN_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2,LOG_TYPE_CONSUME); } /** * Get guild data of the Battleground * @param bg_id ID of the battleground * @return guild of the battleground or NULL. */ struct guild* hBG_get_guild(int bg_id) { struct battleground_data *bgd = bg->team_search(bg_id); struct hBG_data *hBGd; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return NULL; return hBGd->g; } /** * Remove all members from a BG Team. * @param bg_id ID of the battleground. * @param remove Boolean for removal of BG from team_db. * @return 0 on failure, 1 on success. */ int hBG_team_finalize(int bg_id, bool remove) { // Deletes BG Team from db int i; struct map_session_data *sd; struct battleground_data *bgd = bg->team_search(bg_id); struct hBG_data *hBGd; struct guild *g; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return 0; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; hBG_send_dot_remove(sd); sd->bg_id = 0; // Remove Guild Skill Buffs status_change_end(&sd->bl, SC_GUILDAURA, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_BATTLEORDER, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_REGENERATION, INVALID_TIMER); if (sd->status.guild_id && (g = guild->search(sd->status.guild_id)) != NULL) { clif->guild_belonginfo(sd,g); clif->guild_basicinfo(sd); clif->guild_allianceinfo(sd); clif->guild_memberlist(sd); clif->guild_skillinfo(sd); } else { hBG_send_leave_single(sd, sd->status.name, "Leaving Battle..."); } clif->charnameupdate(sd); clif->guild_emblem_area(&sd->bl); } if (remove) { idb_remove(bg->team_db, bg_id); } else { bgd->count = 0; hBGd->leader_char_id = 0; hBGd->team_score = 0; hBGd->created_at = 0; memset(&bgd->members, 0, sizeof(bgd->members)); } return 1; } /** * Give items to the Battleground Team. * @param bg_id ID of the battleground. * @param nameid ID of the item. * @param amount Amount of the Item to be given. * @return void; */ void hBG_team_getitem(int bg_id, int nameid, int amount) { struct battleground_data *bgd; struct map_session_data *sd; struct item_data *id; struct item it; int reward_rate = hBG_config_get("battle_configuration/bg_reward_rates"); int get_amount, j, flag; if (amount < 1 || (bgd = bg->team_search(bg_id)) == NULL || (id = itemdb->exists(nameid)) == NULL) return; if (nameid != 7828 && nameid != 7829 && nameid != 7773) return; if (reward_rate != 100) amount = amount * reward_rate / 100; memset(&it, 0, sizeof(it)); it.nameid = nameid; it.identify = 1; for (j = 0; j < MAX_BG_MEMBERS; j++) { if ((sd = bgd->members[j].sd) == NULL) continue; get_amount = amount; if ((flag = pc->additem(sd,&it,get_amount,LOG_TYPE_SCRIPT))) clif->additem(sd,0,0,flag); } } /** * Give kafra points to the team. * @param bg_id ID of the battleground. * @param amount Amount of kafra points to be given. */ void hBG_team_get_kafrapoints(int bg_id, int amount) { struct battleground_data *bgd; struct map_session_data *sd; int i, get_amount, reward_rate = hBG_config_get("battle_configuration/bg_reward_rates"); if ((bgd = bg->team_search(bg_id)) == NULL) return; if (reward_rate != 100) amount = amount * reward_rate/ 100; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; get_amount = amount; pc->getcash(sd,0,get_amount); } } void hBG_add_rank_points(struct map_session_data *sd, int ranktype, int count) { struct hBG_map_session_data *hBGsd; char message[100]; nullpo_retv(sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; if (ranktype == BG_RANKED) { add2limit(hBGsd->stats.ranked_points, count, MAX_FAME); sprintf(message, "[Battlegrounds Ranked] Your ranking has increased by %d.", count); clif->disp_message(&sd->bl, message, SELF); hookStop(); } else if (ranktype == BG_NORMAL) { add2limit(hBGsd->stats.points, count, MAX_FAME); sprintf(message, "[Battlegrounds Normal] Your ranking has increased by %d.", count); clif->disp_message(&sd->bl, message, SELF); hookStop(); } } /* ============================================================== bg_arena (0 EoS | 1 Boss | 2 TI | 3 CTF | 4 TD | 5 SC | 6 CON | 7 RUSH | 8 DOM) bg_result (0 Won | 1 Tie | 2 Lost) ============================================================== */ void hBG_team_rewards(int bg_id, int nameid, int amount, int kafrapoints, int quest_id, const char *var, int add_value, int bg_arena, int bg_result) { struct battleground_data *bgd = NULL; struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_data *hBGd = NULL; struct item_data *id; struct item it; int j, flag, get_amount, reward_rate = hBG_config_get("battle_configuration/hBG_reward_rates"), fame = 0, type = 0; if (amount < 1 || (bgd = bg->team_search(bg_id)) == NULL || (id = itemdb->exists(nameid)) == NULL) return; if (reward_rate != 100) { // BG Reward Rates amount = amount * reward_rate / 100; kafrapoints = kafrapoints * reward_rate / 100; } memset(&it,0,sizeof(it)); bg_result = cap_value(bg_result, 0, 2); if (nameid == 7828 || nameid == 7829 || nameid == 7773) { it.nameid = nameid; it.identify = 1; } else { nameid = 0; } for (j = 0; j < MAX_BG_MEMBERS; j++) { if ((sd = bgd->members[j].sd) == NULL) continue; else if ((hBGsd = getFromMSD(sd, 1)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) continue; if (quest_id) quest->add(sd, quest_id, 0); pc_setglobalreg(sd, script->add_str(var), pc_readglobalreg(sd,script->add_str(var)) + add_value); if (kafrapoints > 0) { get_amount = kafrapoints; pc->getcash(sd,0,get_amount); } if (nameid && amount > 0) { get_amount = amount; if ((flag = pc->additem(sd,&it,get_amount,LOG_TYPE_SCRIPT))) clif->additem(sd,0,0,flag); } type = hBG_config_get("battle_configuration/hBG_ranked_mode")?BG_RANKED:BG_NORMAL; switch (bg_result) { case 0: // Won add2limit(hBGsd->stats.wins,1,USHRT_MAX); fame = 100; if (sd->status.char_id == hBGd->leader_char_id) { add2limit(hBGsd->stats.wins_as_leader,1,USHRT_MAX); fame += 25; } hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_wins,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_wins,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_wins,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_wins,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_wins,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_wins,1,USHRT_MAX); break; case 6: add2limit(hBGsd->stats.conquest_wins,1,USHRT_MAX); break; case 7: add2limit(hBGsd->stats.ru_wins,1,USHRT_MAX); break; case 8: add2limit(hBGsd->stats.dom_wins,1,USHRT_MAX); break; } break; case 1: // Tie add2limit(hBGsd->stats.ties,1,USHRT_MAX); fame = 75; if (sd->status.char_id == hBGd->leader_char_id) { add2limit(hBGsd->stats.ties_as_leader,1,USHRT_MAX); fame += 10; } hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_tie,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_tie,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_tie,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_tie,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_tie,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_tie,1,USHRT_MAX); break; // No Tie for Conquest or Rush case 8: add2limit(hBGsd->stats.dom_tie,1,USHRT_MAX); break; } break; case 2: // Lost add2limit(hBGsd->stats.losses,1,USHRT_MAX); fame = 50; if (sd->status.char_id == hBGd->leader_char_id) add2limit(hBGsd->stats.losses_as_leader,1,USHRT_MAX); hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_lost,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_lost,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_lost,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_lost,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_lost,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_lost,1,USHRT_MAX); break; case 6: add2limit(hBGsd->stats.conquest_losses,1,USHRT_MAX); break; case 7: add2limit(hBGsd->stats.ru_lost,1,USHRT_MAX); break; case 8: add2limit(hBGsd->stats.dom_lost,1,USHRT_MAX); break; } break; } } } /** * Build BG Guild Emulation data. * @params (void) * @return void. */ void hBG_build_guild_data(void) { int i, j, k, gskill; memset(&bg_guild, 0, sizeof(bg_guild)); for (i = 1; i <= MAX_BATTLEGROUND_TEAMS; i++) { // Emblem Data - Guild ID's FILE* fp = NULL; char gpath[256]; j = i - 1; bg_guild[j].emblem_id = 1; // Emblem Index bg_guild[j].guild_id = SHRT_MAX - j; bg_guild[j].guild_lv = 1; bg_guild[j].max_member = MAX_BG_MEMBERS; // Skills if (j < 3) { // Clan Skills for (k = 0; k < MAX_GUILDSKILL; k++) { gskill = k + GD_SKILLBASE; bg_guild[j].skill[k].id = gskill; switch (gskill) { case GD_GLORYGUILD: bg_guild[j].skill[k].lv = 0; break; case GD_APPROVAL: case GD_KAFRACONTRACT: case GD_GUARDRESEARCH: case GD_BATTLEORDER: case GD_RESTORE: case GD_EMERGENCYCALL: case GD_DEVELOPMENT: bg_guild[j].skill[k].lv = 1; break; case GD_GUARDUP: case GD_REGENERATION: bg_guild[j].skill[k].lv = 3; break; case GD_LEADERSHIP: case GD_GLORYWOUNDS: case GD_SOULCOLD: case GD_HAWKEYES: bg_guild[j].skill[k].lv = 5; break; case GD_EXTENSION: bg_guild[j].skill[k].lv = 10; break; } } } else { // Other Data snprintf(bg_guild[j].name, NAME_LENGTH, "Team %d", i - 3); // Team 1, Team 2 ... Team 10 strncpy(bg_guild[j].master, bg_guild[j].name, NAME_LENGTH); snprintf(bg_guild[j].position[0].name, NAME_LENGTH, "%s Leader", bg_guild[j].name); strncpy(bg_guild[j].position[1].name, bg_guild[j].name, NAME_LENGTH); } sprintf(gpath, "%s/%s/bg_%d.ebm", "plugins","hBG", i); if ((fp = fopen(gpath, "rb")) != NULL) { fseek(fp, 0, SEEK_END); bg_guild[j].emblem_len = (int)ftell(fp); fseek(fp, 0, SEEK_SET); fread(&bg_guild[j].emblem_data, 1, bg_guild[j].emblem_len, fp); fclose(fp); } else { ShowWarning("Error reading '"CL_WHITE"%s"CL_RESET"' emblem data file.\n", gpath); } } ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"' v%s emblem data files. [By Smokexyz]\n", pinfo.name, pinfo.version); // Guild Data - Guillaume strncpy(bg_guild[0].name, "Blue Team", NAME_LENGTH); strncpy(bg_guild[0].master, "General Guillaume", NAME_LENGTH); strncpy(bg_guild[0].position[0].name, "Blue Team Leader", NAME_LENGTH); strncpy(bg_guild[0].position[1].name, "Blue Team", NAME_LENGTH); // Guild Data - Croix strncpy(bg_guild[1].name, "Red Team", NAME_LENGTH); strncpy(bg_guild[1].master, "Prince Croix", NAME_LENGTH); strncpy(bg_guild[1].position[0].name, "Red Team Leader", NAME_LENGTH); strncpy(bg_guild[1].position[1].name, "Red Team", NAME_LENGTH); // Guild Data - Traitors strncpy(bg_guild[2].name, "Green Team", NAME_LENGTH); strncpy(bg_guild[2].master, "Mercenary", NAME_LENGTH); strncpy(bg_guild[2].position[0].name, "Green Team Leader", NAME_LENGTH); strncpy(bg_guild[2].position[1].name, "Green Team", NAME_LENGTH); } /** * Timer function for revealing/hiding mini map positions. * Also handles player AFK mechanic. * @see DBApply * @see hBG_send_xy_timer * @param data battleground data pointer. * @return int */ int hBG_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap) { struct battleground_data *bgd = DB->data2ptr(data); struct hBG_data *hBGd = getFromBGDATA(bgd, 0); char output[128]; int i, m, idle_announce = hBG_config_get("battle_configuration/hBG_idle_announce"), idle_autokick = hBG_config_get("battle_configuration/hBG_idle_autokick"); nullpo_ret(bgd); nullpo_ret(hBGd); m = map->mapindex2mapid(bgd->mapindex); hBGd->reveal_flag = !hBGd->reveal_flag; // Switch for (i = 0; i < MAX_BG_MEMBERS; i++) { struct map_session_data *sd = bgd->members[i].sd; struct hBG_map_session_data *hBGsd = NULL; if (sd == NULL || (hBGsd = getFromMSD(sd, 1)) == NULL) continue; if (idle_autokick && DIFF_TICK(sockt->last_tick, sd->idletime) >= idle_autokick && hBGd->g && map->list[sd->bl.m].flag.battleground) { sprintf(output, "[Battlegrounds] %s has been kicked for being AFK.", sd->status.name); clif->broadcast2(&sd->bl, output, (int)strlen(output)+1, hBGd->color, 0x190, 20, 0, 0, BG); bg->team_leave(sd,3); clif->message(sd->fd, "You have been kicked from the battleground because of your AFK status."); pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3); continue; } else if (sd->bl.x != bgd->members[i].x || sd->bl.y != bgd->members[i].y) { // xy update bgd->members[i].x = sd->bl.x; bgd->members[i].y = sd->bl.y; clif->bg_xy(sd); } if (hBGd->reveal_pos && hBGd->reveal_flag && sd->bl.m == m) map->foreachinmap(hBG_reveal_pos, m, BL_PC, sd, 1, hBGd->color); // Message for AFK Idling if (idle_announce && DIFF_TICK(sockt->last_tick, sd->idletime) >= idle_announce && !hBGsd->state.afk && hBGd->g) { // Set AFK status and announce to the team. hBGsd->state.afk = 1; sprintf(output, "%s : %s seems to be away. AFK Warning - Can be kicked out with @reportafk.", hBGd->g->name, sd->status.name); hBG_send_chat_message(bgd, sd->bl.id, sd->status.name, output, (int)strlen(output) + 1); } } return 0; } /** * Timer function for revealing/hiding mini map positions. * Also handles player AFK time. * @see hBG_send_xy_timer_sub */ int hBG_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { bg->team_db->foreach(bg->team_db, hBG_send_xy_timer_sub, tick); return 0; } /** * Add an item to the floor at m (x,y) * @param bl pointer to the block list. * @param m map index * @param x map x co-ordinate * @param y map y co-ordinate * @param nameid ID of the item to be dropped. * @param amount Amount of the item to be dropped. * @return count of the item dropped. */ int hBG_addflooritem_area(struct block_list* bl, int16 m, int16 x, int16 y, int nameid, int amount) { struct item item_tmp; int count, range, i; short mx, my; memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; if (bl != NULL) m = bl->m; count = 0; range = (int)sqrt((float)amount) +2; for ( i = 0; i < amount; i++) { if (bl != NULL) map->search_freecell(bl, 0, &mx, &my, range, range, 0); else { mx = x; my = y; map->search_freecell(NULL, m, &mx, &my, range, range, 1); } count += (map->addflooritem(bl, &item_tmp, 1, m, mx, my, 0, 0, 0, 4, false) != 0) ? 1 : 0; } return count; } // @TODO void hBG_bg_ranking_display(struct map_session_data *sd, bool ranked) { struct hBG_map_session_data *hBGsd = NULL; nullpo_retv(sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; // print shit. } void hBG_record_mobkills(struct map_session_data *sd, struct mob_data *md) { struct battleground_data *bgd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; nullpo_retv(sd); nullpo_retv(md); if (map->list[sd->bl.m].flag.battleground && sd->bg_id) { int i; if ((bgd = bg->team_search(sd->bg_id)) == NULL) return; if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == sd); if (i >= MAX_BG_MEMBERS) return; switch ( md->class_) { case E_BAPHOMET2: case E_LORD_OF_DEATH2: case E_DARK_LORD: case E_KTULLANUX: case E_DARK_SNAKE_LORD: add2limit(hBGsd->stats.boss_killed, 1, USHRT_MAX); break; case E_TURTLE_GENERAL: case E_APOCALIPS_H: add2limit(hBGsd->stats.guardian_stone_kills, 1, USHRT_MAX); break; case E_FALLINGBISHOP: if (map->list[sd->bl.m].flag.battleground == 2) add2limit(hBGsd->stats.ru_captures, 1, USHRT_MAX); break; case OBJ_NEUTRAL: if (strcmpi(map->list[sd->bl.m].name, "bat_a03") == 0) add2limit(hBGsd->stats.boss_flags, 1, USHRT_MAX); break; case BARRICADE_: if (strcmpi(map->list[sd->bl.m].name, "bat_a01") == 0) add2limit(hBGsd->stats.barricade_kills, 1, USHRT_MAX); break; } } } void hBG_record_damage(struct block_list *src, struct block_list *target, int damage) { struct block_list *s_bl = NULL; struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; if (src == NULL || target == NULL || src == target || damage <= 0) return; if ((s_bl = battle->get_master(src)) == NULL) s_bl = src; if (s_bl->type != BL_PC) return; if ((sd = BL_UCAST(BL_PC, s_bl)) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; switch ( target->type) { case BL_PC: { struct map_session_data *tsd = NULL; struct hBG_map_session_data *hBGtsd = NULL; if ((tsd = BL_UCAST(BL_PC, target)) == NULL) break; if ((hBGtsd = getFromMSD(tsd, 1)) == NULL) break; if (map->list[src->m].flag.battleground && sd->bg_id) { add2limit(hBGsd->stats.total_damage_done, damage, UINT_MAX); add2limit(hBGtsd->stats.total_damage_received, damage, UINT_MAX); if (hBGsd->stats.best_damage < damage) hBGsd->stats.best_damage = damage; } } break; case BL_MOB: { struct mob_data *md = BL_UCAST(BL_MOB, target); if (map->list[src->m].flag.battleground && sd->bg_id && md->class_ >= E_BAPHOMET2 && md->class_ <= E_FALLINGBISHOP) add2limit(hBGsd->stats.boss_damage, damage, USHRT_MAX); } break; } } /** * Warps a Team * @see hBG_warp */ int hBG_team_warp(int bg_id, unsigned short mapidx, short x, short y) { // Warps a Team int i; struct battleground_data *bgd = bg->team_search(bg_id); if (bgd == NULL) { ShowError("buildin_hBG_team_warp: Invalid teamId %d provided!", bg_id); return false; } if (mapidx == 0) { // BG Cemetery (Spawn Point) mapidx = bgd->mapindex; x = bgd->x; y = bgd->y; } for (i = 0; i < bgd->count; i++) if (bgd->members[i].sd != NULL) pc->setpos(bgd->members[i].sd, mapidx, x, y, CLR_TELEPORT); return true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @Commands * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Display battleground rankings. */ ACMD(bgrank) { char mode[7]; char atcmd_output[256]; memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!*message || sscanf(message, "%7s", mode) < 1) { sprintf(atcmd_output, "Please, enter a battleground mode (usage: @bgrank <ranked/normal>)."); clif->message(fd, atcmd_output); return false; } if (strncmpi(mode, "ranked", 7) == 0) { hBG_bg_ranking_display(sd, true); } else if (strncmpi(mode, "normal", 7) == 0) { hBG_bg_ranking_display(sd, true); } else { sprintf(atcmd_output, "Please, enter a battleground mode (usage: @bgrank <ranked/normal>)."); clif->message(fd, atcmd_output); return false; } return true; } ACMD(reportafk) { struct map_session_data *pl_sd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_map_session_data *hBGpl_sd = NULL; struct battleground_data *bgd = NULL; if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) clif->message(fd, "This command is reserved for Battlegrounds Only."); else if (!(hBGd->leader_char_id == sd->status.char_id) && hBG_config_get("battle_configuration/hBG_reportafk_leaderonly")) clif->message(fd, "This command is reserved for Team Leaders Only."); else if (!*message) clif->message(fd, "Please, enter the character name (usage: @reportafk <name>)."); else if ((pl_sd = map->nick2sd(message)) == NULL) clif->message(fd, msg_txt(3)); // Character not found. else if ((hBGpl_sd = getFromMSD(pl_sd, 0)) == NULL) clif->message(fd, "Destination Player is not in battlegrounds."); else if (sd->bg_id != pl_sd->bg_id) clif->message(fd, "Destination Player is not in your Team."); else if (sd == pl_sd) clif->message(fd, "You cannot kick yourself."); else if (!hBGpl_sd->state.afk) clif->message(fd, "The player is not AFK on this Battleground."); else { // Everything is fine! char atcmd_output[256]; // Kick the player and send a message. bg->team_leave(pl_sd, 2); clif->message(pl_sd->fd, "You have been kicked from Battleground because of your AFK status."); pc->setpos(pl_sd, pl_sd->status.save_point.map, pl_sd->status.save_point.x, pl_sd->status.save_point.y, 3); // Message the source player and announce to team. sprintf(atcmd_output, "%s has been successfully kicked.", pl_sd->status.name); clif->broadcast2(&sd->bl, atcmd_output, (int)strlen(atcmd_output)+1, hBGd->color, 0x190, 20, 0, 0, BG); return true; } return false; } /** * Change Team Leader. */ ACMD(leader) { struct map_session_data *pl_sd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_map_session_data *hBGpl_sd = NULL; struct battleground_data *bgd = NULL; if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) clif->message(fd, "This command is reserved for Battlegrounds Only."); else if (sd->ud.skilltimer != INVALID_TIMER) clif->message(fd, "Command not allow while casting a skill."); else if (!(hBG_config_get("battle_configuration/hBG_leader_change"))) clif->message(fd, "This command is disabled."); else if (!(hBGd->leader_char_id == sd->status.char_id)) clif->message(fd, "This command is reserved for Team Leaders Only."); else if (!*message) clif->message(fd, "Please, enter the character name (usage: @leader <name>)."); else if ((pl_sd = map->nick2sd(message)) == NULL) clif->message(fd, msg_txt(3)); // Character not found. else if ((hBGpl_sd = getFromMSD(pl_sd, 0)) == NULL) clif->message(fd, "Destination Player is not in battlegrounds."); else if (sd->bg_id != pl_sd->bg_id) clif->message(fd, "Destination Player is not in your Team."); else if (sd == pl_sd) clif->message(fd, "You are already the Team Leader."); else { // Everything is fine... more or less. char atcmd_output[256]; sprintf(atcmd_output, "Team Leader transfered to [%s]", pl_sd->status.name); clif->broadcast2(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, hBGd->color, 0x190, 20, 0, 0, BG); hBGd->leader_char_id = pl_sd->status.char_id; clif->charnameupdate(sd); clif->charnameupdate(pl_sd); return true; } return false; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Script Commands * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Send out a battleground announcement. * @param mes * @param fontColor * @param fontType * @param fontSize * @param fontAlign * @param fontY */ BUILDIN(hBG_announce) { const char *mes = script_getstr(st,2); const char *fontColor = script_hasdata(st,3) ? script_getstr(st,3) : NULL; int fontType = script_hasdata(st,4) ? script_getnum(st,4) : 0x190; // default fontType (FW_NORMAL) int fontSize = script_hasdata(st,5) ? script_getnum(st,5) : 12; // default fontSize int fontAlign = script_hasdata(st,6) ? script_getnum(st,6) : 0; // default fontAlign int fontY = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontY clif->broadcast2(NULL, mes, (int)strlen(mes) + 1, (unsigned int)strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, ALL_CLIENT); return true; } /** * Count the number of logins per IP in battleground * @return count of accounts on same ip. */ BUILDIN(hBG_logincount) { struct map_session_data *sd = script->rid2sd(st); int i = 0; if (sd) i = hBG_countlogin(sd,true); script_pushint(st,i); return true; } /** * Create a BG Team. * @param map_name Respawn Map Name * @param map_x Respawn Map X * @param map_y Respawn Map Y * @param guild_index BG Guild Index * @param ev Logout Event * @param dev Die Event */ BUILDIN(hBG_team_create) { const char *map_name, *ev = "", *dev = ""; int x, y, m = 0, guild_index, bg_id; map_name = script_getstr(st, 2); if (strcmp(map_name,"-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 3); y = script_getnum(st, 4); guild_index = script_getnum(st, 5); ev = script_getstr(st, 6); // Logout Event dev = script_getstr(st, 7); // Die Event guild_index = cap_value(guild_index, 0, 12); bg_id = hBG_create(m, x, y, guild_index, ev, dev); script_pushint(st, bg_id); return true; } /** * Create a Queue * @param queue_name Name of the Queue * @param jev Join Event * @param min_level Minimum level to join the queue. * @return queue Id */ BUILDIN(hBG_queue_create) { const char *queue_name, *jev; int min_level = 0; queue_name = script_getstr(st, 2); jev = script_getstr(st, 3); if (script_hasdata(st, 4)) min_level = script_getnum(st, 4); script_pushint(st, hBG_queue_create(queue_name, jev, min_level)); return true; } /** * Changes/Sets the Queue's Join Event. * @param queue_id * @param jev On Join Event */ BUILDIN(hBG_queue_event) { struct hBG_queue_data *hBGqd; const char *join_event; int q_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st, 0); return false; } join_event = script_getstr(st,3); safestrncpy(hBGqd->join_event, join_event, sizeof(hBGqd->join_event)); script_pushint(st, 1); return true; } /** * Makes a player join a queue. * @param Queue ID */ BUILDIN(hBG_queue_join) { int q_id; struct map_session_data *sd = script->rid2sd(st); nullpo_retr(false, sd); q_id = script_getnum(st,2); script_pushint(st, hBG_queue_join(sd, q_id)); return true; } /** * Makes party join a queue. * @param Party ID * @param Queue ID */ BUILDIN(hBG_queue_partyjoin) { int q_id, i, party_id; struct map_session_data *sd; struct party_data *p; party_id = script_getnum(st,2); if (party_id <= 0 || (p = party->search(party_id)) == NULL) { script_pushint(st, 0); return false; } q_id = script_getnum(st,3); if (hBG_queue_search(q_id) == NULL) { script_pushint(st, 0); return false; } for (i = 0; i < MAX_PARTY; i++) { if ((sd = p->data[i].sd) == NULL) continue; hBG_queue_join(sd,q_id); } script_pushint(st, 1); return true; } /** * Makes a player leave a queue. * @param Queue ID */ BUILDIN(hBG_queue_leave) { int q_id; struct map_session_data *sd = script->rid2sd(st); nullpo_retr(false, sd); q_id = script_getnum(st,2); script_pushint(st, hBG_queue_leave(sd, q_id)); return true; } /** * Request queue information * @param Queue ID * @param Information Type * 0) Users * 1) Copy user list to $@qmembers$ variable and return count. */ BUILDIN(hBG_queue_data) { struct hBG_queue_data *hBGqd; int q_id = script_getnum(st,2), type = script_getnum(st,3); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st,0); return false; } switch (type) { case 0: script_pushint(st, hBGqd->users); return true; case 1: // User List { int j = 0; struct map_session_data *sd; struct hBG_queue_member *head; head = hBGqd->first; while (head) { if ((sd = head->sd) != NULL) { mapreg->setregstr(reference_uid(script->add_str("$@qmembers$"),j),sd->status.name); j++; } head = head->next; } script_pushint(st,j); } return true; default: ShowError("script:hBG_queue_data: unknown queue data type %d.\n", type); break; } script_pushint(st, 0); return true; } /** * Adds all members in queue to a BG team. * @param Queue ID * @param Max Team Members * @param Respawn Map Name * @param Respawn Map X * @param Respawn Map Y * @param BG Guild Index * @param Logout Event * @param Die Event * @return Battleground Id */ BUILDIN(hBG_queue2team) { struct hBG_queue_data *hBGqd; struct hBG_queue_member *qm; const char *map_name, *ev = "", *dev = ""; int q_id, max, x, y, i, m=0, guild_index, bg_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st, 0); return false; } max = script_getnum(st,3); map_name = script_getstr(st,4); if (strcmp(map_name,"-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st,5); y = script_getnum(st,6); guild_index = script_getnum(st,7); ev = script_getstr(st,8); // Logout Event dev = script_getstr(st,9); // Die Event guild_index = cap_value(guild_index, 0, 12); if ((bg_id = hBG_create(m, x, y, guild_index, ev, dev)) == 0) { script_pushint(st, 0); return false; } i = 0; // Counter while ((qm = hBGqd->first) != NULL && i < max && i < MAX_BG_MEMBERS) { if (qm->sd && hBG_team_join(bg_id, qm->sd)) { mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), qm->sd->bl.id); hBG_queue_member_remove(hBGqd, qm->sd->bl.id); i++; } else { break; // Failed? Should not. Anyway, to avoid a infinite loop } } mapreg->setreg(script->add_str("$@arenamembersnum"), i); script_pushint(st, bg_id); return true; } /** * Joins the first player in the queue to the given team and warps him. * @param Queue ID * @param Battleground ID * @param Spawn Map Name * @param Spawn Map X Co-ordinate * @param Spawn Map Y Co-ordinate */ BUILDIN(hBG_queue2team_single) { const char* map_name; struct hBG_queue_data *hBGqd; struct map_session_data *sd; int x, y, m, bg_id, q_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL || !hBGqd->first || !hBGqd->first->sd) { script_pushint(st, 0); return false; } bg_id = script_getnum(st, 3); map_name = script_getstr(st, 4); if ((m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 5); y = script_getnum(st, 6); sd = hBGqd->first->sd; if (hBG_team_join(bg_id, sd)) { hBG_queue_member_remove(hBGqd, sd->bl.id); pc->setpos(sd, m, x, y, CLR_TELEPORT); script_pushint(st, 1); } return true; } /** * Check if the given BG Queue can start a BG in the given mode. * @param Queue ID * @param Type * @param Teams * @param Required Minimum Players * @return 1 can start, 0 cannot start. */ BUILDIN(hBG_queue_checkstart) { int q_id, result = 0; struct hBG_queue_data *hBGqd; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) != NULL) { int type, req_min, teams; type = script_getnum(st,3); teams = script_getnum(st,4); req_min = script_getnum(st,5); switch (type) { case 0: // Lineal, as they Join case 1: // Random if (hBGqd->users >= (req_min * teams)) result = 1; break; default: result = 0; break; } } script_pushint(st, result); return true; } /** * Build BG Teams from one Queue * @param Queue ID * @param Minimum Players * @param Maximum Players per Team * @param Type * @param ... Team ID */ BUILDIN(hBG_queue2teams) { // Send Users from Queue to Teams. Requires previously created teams. struct hBG_queue_data *hBGqd; int t, bg_id = 0, total_teams = 0, q_id, min, max, type, limit = 0; int arg_offset = 6; struct map_session_data *sd; q_id = script_getnum(st,2); // Queue ID if ((hBGqd = hBG_queue_search(q_id)) == NULL) { ShowError("buildin_hBG_queue2teams: Non existant queue id received %d.\n", q_id); script_pushint(st, 0); return false; } min = script_getnum(st,3); // Min Members per Team max = script_getnum(st,4); // Max Members per Team type = script_getnum(st,5); // Team Building Method t = arg_offset; // Team ID's to build while (script_hasdata(st,t) && t < MAX_BATTLEGROUND_TEAMS+arg_offset) { bg_id = script_getnum(st,t); if (bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_queue2teams: Non existant team Id received %d.\n", bg_id); script_pushint(st, 0); return false; } t++; } total_teams = t - arg_offset; if (total_teams < 2) { ShowError("buildin_hBG_queue2teams: Less than 2 teams received to build members.\n"); script_pushint(st, 0); return false; } if (hBGqd->users < min) { ShowError("buildin_hBG_queue2teams: Less than minimum %d queue members received (%d).\n", min, (int) hBGqd->users); script_pushint(st, 0); return false; } // How many players are we going to take from the Queue limit = min(max * total_teams, hBGqd->users); switch (type) { case 0: // Lineal - Maybe to keep party together { t = 0; int i = 0; for (i = 0; i < limit; i++) { if ((i%(limit/total_teams)) == 0) // Switch Team bg_id = script_getnum(st,t+arg_offset); if (!hBGqd->first || (sd = hBGqd->first->sd) == NULL) break; // No more people to join Teams hBG_team_join(bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); // Increment Team counter or break if (t++ >= total_teams) break; } } break; default: case 1: // Random { t = 0; int pos = 0, i=0; struct hBG_queue_member *qm; for (i=0; t < limit; i++) { if ((i%(limit/total_teams)) == 0) // Switch Team bg_id = script_getnum(st,t+arg_offset); pos = 1 + rand() % (limit - i); if ((qm = hBG_queue_member_get(hBGqd, pos)) == NULL || (sd = qm->sd) == NULL) break; hBG_team_join(bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); // Increment Team Counter or break if (t++ >= total_teams) break; } } break; } script_pushint(st, 1); return true; } /** * Fill teams with members from the given Queue. * @param Queue ID * @param Max Players Per Team * @param Balanceing method * @param Team 1 ... Team 13 */ BUILDIN(hBG_balance_teams) { struct hBG_queue_data *hBGqd; struct hBG_queue_member *head; struct battleground_data *bgd, *p_bg; int i, c, q_id, bg_id, m_bg_id = 0, max, min, type; struct map_session_data *sd; bool balanced; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL || hBGqd->users <= 0) { ShowError("buildin_hBG_balance_teams: Non existant Queue Id or the queue is empty.\n"); script_pushint(st, 0); return false; } max = script_getnum(st,3); if (max > MAX_BG_MEMBERS) max = MAX_BG_MEMBERS; min = MAX_BG_MEMBERS + 1; type = script_getnum(st, 4); i = 5; // Team IDs to build while (script_hasdata(st, i) && i-5 < 13) { bg_id = script_getnum(st, i); if ((bgd = bg->team_search(bg_id)) == NULL) { ShowError("buildin_hBG_balance_teams: Non existant team id received %d.\n", bg_id); script_pushint(st, 0); return false; } if (bgd->count < min) min = bgd->count; i++; } c = i - 5; // Teams Found if (c < 2 || min >= max) return true; // No Balance Required if (type < 3) { while ((head = hBGqd->first) != NULL && (sd = head->sd) != NULL) { p_bg = NULL; balanced = true; min = MAX_BG_MEMBERS + 1; // Search the Current Minimum and Balance status for (i = 0; i < c; i++) { bg_id = script_getnum(st,i+5); if ((bgd = bg->team_search(bg_id)) == NULL) break; // Should not happen. Teams already check if (p_bg && p_bg->count != bgd->count) balanced = false; // Teams still with different member count if (bgd->count < min) { m_bg_id = bg_id; min = bgd->count; } p_bg = bgd; } if (min >= max) break; // Balance completed if (hBG_config_get("battle_configuration/hBG_balanced_queue") && balanced && hBGqd->users < c) break; // No required users on queue to keep balance hBG_team_join(m_bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); if ((bgd = bg->team_search(m_bg_id)) != NULL && bgd->mapindex) pc->setpos(sd, bgd->mapindex, bgd->x, bgd->y, CLR_TELEPORT); // Joins and Warps } } else { ShowError("buildin_hBG_balance_teams: Invalid type %d given for argument #3.\n", type); script_pushint(st, 0); return false; } script_pushint(st, 1); return true; } /** * Waiting Room to Battleground Teams * @param Map Name * @param Map X * @param Map Y * @param BG Guild Index * @param Logout Event * @param Die Event */ BUILDIN(hBG_waitingroom2bg) { struct npc_data *nd; struct chat_data *cd; const char *map_name, *ev = "", *dev = ""; int x, y, i, m=0, guild_index, bg_id; struct map_session_data *sd; nd = (struct npc_data *)map->id2bl(st->oid); if (nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL) { script_pushint(st, 0); return false; } map_name = script_getstr(st,2); if (strcmp(map_name, "-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 3); y = script_getnum(st, 4); guild_index = script_getnum(st, 5); ev = script_getstr(st, 6); // Logout Event dev = script_getstr(st, 7); // Die Event guild_index = cap_value(guild_index, 0, 12); if ((bg_id = hBG_create(m, x, y, guild_index, ev, dev)) == 0) { // Creation failed script_pushint(st, 0); return false; } for (i = 0; i < cd->users && i < MAX_BG_MEMBERS; i++) { if ((sd = cd->usersd[i]) != NULL && hBG_team_join(bg_id, sd)) mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), sd->bl.id); else mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), 0); } mapreg->setreg(script->add_str("$@arenamembersnum"), i); script_pushint(st, bg_id); return true; } /** * Adds the first player from the given NPC's * waiting room to BG Team. * @param Battleground Id * @param Map Name * @param Map X * @param Map Y * @param NPC Name */ BUILDIN(hBG_waitingroom2bg_single) { const char* map_name; struct npc_data *nd; struct chat_data *cd; struct map_session_data *sd; int x, y, m, bg_id; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if ((m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; // Invalid Map } x = script_getnum(st,4); y = script_getnum(st,5); nd = npc->name2id(script_getstr(st,6)); if (nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL || cd->users <= 0) { script_pushint(st, 0); return false; } if ((sd = cd->usersd[0]) == NULL) { script_pushint(st, 0); return false; } if (hBG_team_join(bg_id, sd)) { pc->setpos(sd, m, x, y, CLR_TELEPORT); script_pushint(st,1); } else { script_pushint(st,0); } return true; } /** * Set the Respawn Location of a BG team * @param Battleground Id * @param Map X * @param Map Y */ BUILDIN(hBG_team_setxy) { struct battleground_data *bgd; int bg_id; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL) { script_pushint(st, 0); return false; } bgd->x = script_getnum(st,3); bgd->y = script_getnum(st,4); script_pushint(st, 1); return true; } /** * Reveal the location of a BG Team on the minimap. * @param Battleground ID */ BUILDIN(hBG_team_reveal) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } hBGd->reveal_pos = true; // Reveal Position Mode script_pushint(st, 1); return true; } /** * Conceal the location of a BG Team from the minimap. * @param Battleground ID */ BUILDIN(hBG_team_conceal) { struct battleground_data *bgd; struct hBG_data *hBGd; struct map_session_data *sd; int bg_id,i=0; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; hBG_send_dot_remove(sd); } hBGd->reveal_pos = false; // Conceal Position Mode script_pushint(st, 1); return true; } /** * Set Quest for a BG Team * @param Battleground ID * @param Quest ID */ BUILDIN(hBG_team_setquest) { struct battleground_data *bgd; struct map_session_data *sd; int i, bg_id, qid; bg_id = script_getnum(st,2); qid = script_getnum(st,3); if (bg_id <= 0 || (bgd = bg->team_search(bg_id)) == NULL) { ShowError("buildin_hBG_team_setquest: Invalid Team ID %d given.\n", bg_id); script_pushint(st, 0); return false; } if (qid <= 0 || quest->db(qid) == NULL) { ShowError("buildin_hBG_team_setquest: Invalid Quest ID %d given.\n", qid); script_pushint(st, 0); return false; } for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; quest->add(sd, qid, 0); } script_pushint(st, 1); return true; } /** * Set Viewpoint for a player. * @see hBG_viewpointmap */ int hBG_viewpointmap_sub(struct block_list *bl, va_list ap) { struct map_session_data *sd; int npc_id, type, x, y, id, color; npc_id = va_arg(ap,int); type = va_arg(ap,int); x = va_arg(ap,int); y = va_arg(ap,int); id = va_arg(ap,int); color = va_arg(ap,int); sd = (struct map_session_data *)bl; clif->viewpoint(sd,npc_id,type,x,y,id,color); return 0; } /** * Set Viewpoint on minimap for a player. * @param Map Name * @param Type * 0 = display mark for 15 seconds * 1 = display mark until dead or teleported * 2 = remove mark * @param Map X * @param Map Y * @param ID (Unique ID of the viewpoint) * @param Color */ BUILDIN(hBG_viewpointmap) { int type,x,y,id,color,m; const char *map_name; map_name = script_getstr(st,2); if ((m = map->mapname2mapid(map_name)) < 0) { script_pushint(st, 0); return false; // Invalid Map } type=script_getnum(st,3); x=script_getnum(st,4); y=script_getnum(st,5); id=script_getnum(st,6); color=script_getnum(st,7); map->foreachinmap(hBG_viewpointmap_sub,m,BL_PC,st->oid,type,x,y,id,color); script_pushint(st, 1); return true; } /** * Reveal a monster's location on minimap * @param Monster Id * @param Type * 0 = display mark for 15 seconds * 1 = display mark until dead or teleported * 2 = remove mark * @param Color */ BUILDIN(hBG_monster_reveal) { struct block_list *mbl; int id = script_getnum(st,2), flag = script_getnum(st,3), color = script_getnum(st,4); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } map->foreachinmap(hBG_viewpointmap_sub, mbl->m, BL_PC, st->oid, flag, mbl->x, mbl->y, mbl->id, color); script_pushint(st, 1); return true; } /** * Set monster as an ally to a BG Team. * @param Monster ID * @param Battleground ID */ BUILDIN(hBG_monster_set_team) { struct mob_data *md; struct block_list *mbl; int id = script_getnum(st,2), bg_id = script_getnum(st,3); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } md = (TBL_MOB *)mbl; md->bg_id = bg_id; mob_stop_attack(md); mob_stop_walking(md, 0); md->target_id = md->attacked_id = 0; clif->charnameack(0, &md->bl); script_pushint(st, 1); return true; } /** * Set immunity flag to a monster. * (making it immune to damage). * @param Monster ID * @param Flag (0 = Off | 1 = On) */ BUILDIN(hBG_monster_immunity) { struct mob_data *md; struct block_list *mbl; struct hBG_mob_data *hBGmd; int id = script_getnum(st,2), flag = script_getnum(st,3); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } md = (TBL_MOB *)mbl; if ((hBGmd = getFromMOBDATA(md, 0)) == NULL){ CREATE(hBGmd, struct hBG_mob_data, 1); addToMOBDATA(md, hBGmd, 0, true); } hBGmd->state.immunity = flag; return true; } /** * Leave a Battleground Team */ BUILDIN(hBG_leave) { struct map_session_data *sd = script->rid2sd(st); if (sd == NULL || sd->bg_id == 0) { script_pushint(st, 0); return false; } bg->team_leave(sd,0); script_pushint(st, 1); return true; } /** * Finalize battlegrounds and remove * teams from the db. */ BUILDIN(hBG_destroy) { int bg_id = script_getnum(st, 2); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_destroy: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } hBG_team_finalize(bg_id, true); script_pushint(st, 1); return true; } /** * Clean Battlegrounds without removing * the teams from the db. */ BUILDIN(hBG_clean) { int bg_id = script_getnum(st, 2); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_clean: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } hBG_team_finalize(bg_id, false); script_pushint(st, 1); return true; } /** * Get user count within an area in a map. * @param Battleground ID * @param Map Name * @param X1 * @param Y1 * @param X2 * @param Y2 */ BUILDIN(hBG_getareausers) { struct battleground_data *bgd = NULL; struct map_session_data *sd = NULL; const char *map_name; int m, x0, y0, x1, y1, bg_id; int i = 0, c = 0; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if ((bgd = bg->team_search(bg_id)) == NULL || (m = map->mapname2mapid(map_name)) < 0) { script_pushint(st,0); return false; } x0 = script_getnum(st,4); y0 = script_getnum(st,5); x1 = script_getnum(st,6); y1 = script_getnum(st,7); for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; else if (sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) continue; c++; } script_pushint(st, c); return true; } /** * Update the score on a battleground map. * @param Map Name * @param Lion Score * @param Eagle Score */ BUILDIN(hBG_updatescore) { const char *map_name; int m; map_name = script_getstr(st,2); if ((m = map->mapname2mapid(map_name)) < 0) { script_pushint(st, 0); return false; } map->list[m].bgscore_lion = script_getnum(st,3); map->list[m].bgscore_eagle = script_getnum(st,4); clif->bg_updatescore(m); script_pushint(st, 1); return true; } /** * Update Score for a Battleground Team. * @param Battleground ID * @param Score */ BUILDIN(hBG_update_score_team) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2); int score = script_getnum(st,3); if (bg_id <= 0) { ShowError("buildin_hBG_update_score_team: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } hBGd->team_score = score; hBG_update_score_team(bgd); script_pushint(st, 1); return true; } /** * Get a Team's Guild Index * @param Battleground ID * @return Guild Index */ BUILDIN(hBG_get_team_gid) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2), guild_id = 0; if (bg_id <= 0) { ShowError("buildin_hBG_get_team_gid: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) guild_id = hBGd->g->guild_id; script_pushint(st, guild_id); return true; } /** * Get data from a Battleground * @param Battleground ID * @param Type * 0 = User Count * 1 = Fill $@bgmembers$ array with user list and return user count. * 2 = BG Guild Name * 3 = BG Guild Master Name * 4 = BG Color */ BUILDIN(hBG_get_data) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2); int type = script_getnum(st,3); if (bg_id <= 0) { ShowError("buildin_hBG_get_data: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } switch (type) { case 0: script_pushint(st, bgd->count); break; case 1: // Users and List { int i, j = 0; struct map_session_data *sd; for (i = 0; i < bgd->count; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; mapreg->setregstr(reference_uid(script->add_str("$@bgmembers$"),j),sd->status.name); j++; } script_pushint(st, j); } break; case 2: script_pushconststr(st,hBGd->g ? hBGd->g->name : ""); break; case 3: script_pushconststr(st,hBGd->g ? hBGd->g->master : ""); break; case 4: script_pushint(st,hBGd->color); break; default: ShowError("script:bg_get_data: unknown data identifier %d\n", type); break; } script_pushint(st, 0); return true; } /** * Battleground Get Item * @param Battleground ID * @param Item ID * @param Item Amount */ BUILDIN(hBG_getitem) { int bg_id, nameid, amount; bg_id = script_getnum(st,2); nameid = script_getnum(st,3); amount = script_getnum(st,4); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_getitem: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } else if (nameid <= 0 || itemdb->exists(nameid) == NULL) { ShowError("buildin_hBG_getitem: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } else if (amount <= 0) { ShowError("buildin_hBG_getitem: Invalid Item amount %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_team_getitem(bg_id, nameid, amount); script_pushint(st, amount); return true; } /** * Battleground Get Kafra Points * @param Battleground ID * @param Amount of KP */ BUILDIN(hBG_getkafrapoints) { int bg_id, amount; bg_id = script_getnum(st, 2); amount = script_getnum(st, 3); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_getkafrapoints: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } else if (amount <= 0) { ShowError("buildin_hBG_getkafrapoints: Invalid Kafra Points %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_team_get_kafrapoints(bg_id, amount); script_pushint(st, amount); return true; } /** * Battleground get Rewards * @param Battleground ID * @param Item ID * @param Item Amount * @param Kafra Points * @param Quest ID * @param Custom Variable (#KAFRAPOINTS/#CASHPOINTS etc..) * @param Custom Variable Add Value * @param Battleground Arena (0 EoS | 1 Boss | 2 TI | 3 CTF | 4 TD | 5 SC | 6 CON | 7 RUSH | 8 DOM) * @param Battleground Result (0 Won | 1 Tie | 2 Lost) */ BUILDIN(hBG_reward) { int bg_id, nameid, amount, kafrapoints, quest_id, add_value, bg_arena, bg_result; const char *var; bg_id = script_getnum(st,2); nameid = script_getnum(st,3); amount = script_getnum(st,4); kafrapoints = script_getnum(st,5); quest_id = script_getnum(st,6); var = script_getstr(st,7); add_value = script_getnum(st,8); bg_arena = script_getnum(st,9); bg_result = script_getnum(st,10); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_reward: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if (nameid <= 0 || itemdb->exists(nameid) == NULL) { ShowError("buildin_hBG_reward: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } if (nameid > 0 && amount <= 0) { ShowError("buildin_hBG_reward: Invalid Item amount %d provided.\n", nameid); script_pushint(st, 0); return false; } if (kafrapoints < 0) { ShowError("buildin_hBG_reward: Invalid Kafra Points %d provided.\n", kafrapoints); script_pushint(st, 0); return false; } if (quest_id < 0 || quest->db(quest_id) == NULL) { ShowError("buildin_hBG_reward: Invalid Quest ID %d provided.\n", quest_id); script_pushint(st, 0); return false; } if (bg_arena < 0) { ShowError("buildin_hBG_reward: Invalid BG Arena %d provided. \n", bg_arena); script_pushint(st, 0); return false; } if (bg_result < 0 || bg_result > 2) { ShowError("buildin_hBG_reward: Invalid BG result type %d provided. (types - 0 Won | 1 Tie | 2 Lost)", bg_result); script_pushint(st, 0); return false; } hBG_team_rewards(bg_id, nameid, amount, kafrapoints, quest_id, var, add_value, bg_arena, bg_result); script_pushint(st, 1); return true; } /** * Add Item to XY co-ordinates on Floor. * @param Map Name * @param Map X * @param Map Y * @param Item ID * @param Item Amount */ BUILDIN(hBG_flooritem2xy) { int nameid, amount, m, x, y; const char *mapname; mapname = script_getstr(st,2); if ((m = map->mapname2mapid(mapname)) < 0) { // error message is thrown through mapindex->name2id() script_pushint(st, 0); return false; } x = script_getnum(st,3); y = script_getnum(st,4); nameid = script_getnum(st,5); if (itemdb->search(nameid) == NULL) { ShowError("buildin_hBG_flooritem2xy: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } amount = script_getnum(st,6); if (amount < 1) { ShowError("buildin_hBG_flooritem2xy: Invalid Item amount %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_addflooritem_area(NULL, m, x, y, nameid, amount); script_pushint(st, amount); return true; } /** * Warps BG Team to destination or Respawn Point * @param BG Team * @param Map Name * @param Map X * @param Map Y */ BUILDIN(hBG_warp) { int x, y, mapidx, bg_id; const char *map_name; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if (!strcmp(map_name,"RespawnPoint")) // Cemetery Zone mapidx = 0; else if ((mapidx = script->mapindexname2id(st,map_name)) == 0) return 0; // Invalid Map x = script_getnum(st,4); y = script_getnum(st,5); bg_id = hBG_team_warp(bg_id, mapidx, x, y); return true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Map Server Function Pre-Hooks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * NPC Pre-Hooks */ void npc_parse_unknown_mapflag_pre(const char **name, const char **w3, const char **w4, const char **start, const char **buffer, const char **filepath, int **retval) { int16 m = map->mapname2mapid(*name); if (strcmpi(*w3, "hBG_topscore") == 0) { struct hBG_mapflag *hBG_mf; if ((hBG_mf = getFromMAPD(&map->list[m], 0)) == NULL) { CREATE(hBG_mf, struct hBG_mapflag, 1); hBG_mf->hBG_topscore = 1; addToMAPD(&map->list[m], hBG_mf, 0, true); } hBG_mf->hBG_topscore = 1; hookStop(); } return; } /** * Clif Pre-Hooks */ void clif_charnameupdate_pre(struct map_session_data **sd) { unsigned char buf[103]; int cmd = 0x195, ps; struct battleground_data *bgd = bg->team_search((*sd)->bg_id); struct hBG_data *hBGd; nullpo_retv((*sd)); if ((*sd)->fakename[0] || bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL || hBGd->g == NULL) return; //No need to update as the guild was not displayed anyway. WBUFW(buf,0) = cmd; WBUFL(buf,2) = (*sd)->bl.id; memcpy(WBUFP(buf,6), (*sd)->status.name, NAME_LENGTH); WBUFB(buf,30) = 0; memcpy(WBUFP(buf,54), hBGd->g->name, NAME_LENGTH); ps = (hBGd->leader_char_id == (*sd)->status.char_id)?0:1; memcpy(WBUFP(buf,78), hBGd->g->position[ps].name, NAME_LENGTH); // Update nearby clients clif->send(buf, 102, &(*sd)->bl, AREA); hookStop(); } //Prevent update Guild Info if you're in BG void clif_parse_GuildRequestInfo_pre(int *fd, struct map_session_data **sd) { if ((*sd) && (*sd)->bg_id) hookStop(); return; } /** * Skill Pre-Hooks. */ int skill_check_condition_castbegin_pre(struct map_session_data **sd, uint16 *skill_id, uint16 *skill_lv) { nullpo_ret(sd); if (map->list[(*sd)->bl.m].flag.battleground && (*skill_id >= GD_SKILLBASE && *skill_id <= GD_DEVELOPMENT)) hookStop(); // Prevent original function from running after return from here. return 1; } int skillnotok_pre(uint16 *skill_id, struct map_session_data **sd) { int16 idx, m; nullpo_retr(1, *sd); m = (*sd)->bl.m; idx = skill->get_index(*skill_id); if (map->list[m].flag.battleground && (*skill_id >= GD_SKILLBASE && *skill_id <= GD_DEVELOPMENT)) { if (pc_has_permission(*sd, PC_PERM_DISABLE_SKILL_USAGE)) { hookStop(); return 1; } if (pc_has_permission(*sd, PC_PERM_SKILL_UNCONDITIONAL)) { hookStop(); return 0; // can do any damn thing they want } if ((*sd)->blockskill[idx]) { clif->skill_fail((*sd), *skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); hookStop(); return 1; } hookStop(); } return 0; } /** * Skill cast end. * @param src = source block list. * @param bl = target block list */ int skill_castend_nodamage_id_pre(struct block_list **src, struct block_list **bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { struct map_session_data *sd, *dstsd; struct status_change *tsc; struct status_data *sstatus; struct hBG_map_session_data *hBGsd = NULL; nullpo_retr(1, bl); nullpo_retr(1, src); if (!map->list[(*src)->m].flag.battleground || *skill_id != GD_EMERGENCYCALL) return 0; sd = BL_CAST(BL_PC, *src); dstsd = BL_CAST(BL_PC, *bl); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return 0; tsc = status->get_sc(*bl); sstatus = status->get_status_data(*src); switch (*skill_id) { case GD_EMERGENCYCALL: { int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; int i = 0, j = 0; struct guild *g; // i don't know if it actually summons in a circle, but oh well. ;P if (sd && (g = hBG_get_guild(sd->bg_id)) != NULL) { clif->skill_nodamage(*src, *bl, *skill_id, *skill_lv, 1); for (i = 0; i < g->max_member; i++, j++) { if (j>8) j=0; if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { if (map->getcell((*src)->m, *src, (*src)->x + dx[j], (*src)->y + dy[j], CELL_CHKNOREACH)) dx[j] = dy[j] = 0; pc->setpos(dstsd, map_id2index((*src)->m), (*src)->x+dx[j], (*src)->y+dy[j], CLR_RESPAWN); } } guild->block_skill(sd, skill->get_time2(*skill_id, *skill_lv)); } } break; case HLIF_HEAL: case AL_HEAL: { struct mob_data *dstmd = BL_UCAST(BL_MOB, *bl); int heal = skill->calc_heal(*src, *bl, *skill_id, *skill_lv, true); if (status->isimmune(*bl) || (dstmd && dstmd->class_ == MOBID_EMPELIUM)) heal = 0; if (dstmd && mob_is_battleground(dstmd)) heal = 1; if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->job&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0) heal = heal*2; if (tsc && tsc->count) { if (tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS)) { //Bounce back heal if (src == bl) heal=0; //When you try to heal yourself under Kaite, the heal is voided. else { bl = src; dstsd = sd; } } else if (tsc->data[SC_BERSERK]) { heal = 0; //Needed so that it actually displays 0 when healing. } } if (sd && dstsd && heal > 0 && sd != dstsd) { if (map->list[(*src)->m].flag.battleground && sd->bg_id && dstsd->bg_id) { if (sd->bg_id == dstsd->bg_id) add2limit(hBGsd->stats.healing_done, heal, UINT_MAX); else add2limit(hBGsd->stats.wrong_healing_done, heal, UINT_MAX); } } } break; } hookStop(); return 0; } /** * Status Pre-Hooks */ int status_get_guild_id_pre(const struct block_list **bl) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; nullpo_ret((*bl)); if ((*bl)->type == BL_PC && (bg_id = bg->team_get_id((struct block_list *)*bl)) > 0 && (bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && hBGd->g) { hookStop(); return hBGd->g->guild_id; } return 0; } int status_get_emblem_id_pre(const struct block_list **bl) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; nullpo_ret(bl); if ((*bl)->type == BL_PC && (bg_id = bg->team_get_id((struct block_list *)(*bl))) > 0 && (bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && hBGd->g) { hookStop(); return hBGd->g->emblem_id; } return 0; } /** * Guild Pre-Hooks */ // Check if guild is null and don't run BCT checks if true. bool guild_isallied_pre(int *guild_id, int *guild_id2) { struct guild *g = guild->search(*guild_id); if (g == NULL) { hookStop(); return false; } return false; } /** * Unit Pre-Hooks */ int unit_free_pre(struct block_list **bl, clr_type *clrtype) { nullpo_retr(0, (*bl)); if ((*bl)->type == BL_PC) { struct map_session_data *sd = BL_UCAST(BL_PC, (*bl)); struct hBG_queue_data *hBGqd = NULL; struct battleground_data *bgd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; if ((hBGqd = getFromMSD(sd, 0)) && hBG_queue_member_search(hBGqd, sd->bl.id)) hBG_queue_member_remove(hBGqd, sd->bl.id); if (sd->bg_id != 0 && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && (hBGsd = getFromMSD(sd, 1)) != NULL) { bg->team_leave(sd, 1); hBGsd->stats.total_deserted++; } removeFromMSD(sd, 1); } return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Map Server Function Post-Hooks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Battle Post-Hooks */ void battle_consume_ammo(struct map_session_data *sd, int skill_id, int lv) { int qty = 1; struct hBG_map_session_data *hBGsd = getFromMSD(sd, 1); if (battle->bc->arrow_decrement == 0 || hBGsd == NULL) return; if (skill) qty = max(1, skill->get_ammo_qty(skill_id, lv)); if (sd->equip_index[EQI_AMMO] >= 0) { if (sd->bg_id && map->list[sd->bl.m].flag.battleground) add2limit(hBGsd->stats.ammo_used, qty, UINT_MAX); } } // Check target immunity int battle_check_target_post(int retVal, struct block_list *src, struct block_list *target, int flag) { if (retVal == 1 && target->type == BL_MOB) { struct mob_data *md = BL_UCAST(BL_MOB, target); struct hBG_mob_data *hBGmd = NULL; if (md == NULL || (hBGmd = getFromMOBDATA(md, 0)) == NULL) return retVal; if (hBGmd != NULL && hBGmd->state.immunity) { hookStop(); return retVal; } } return retVal; } /** * Clif Post-Hooks */ void clif_parse_LoadEndAck_post(int fd, struct map_session_data *sd) { clif->charnameupdate(sd); /* Display emblem on head of char [lucaslsb] */ if (hBG_enabled && sd->state.changemap && map->list[sd->bl.m].flag.battleground) clif->map_type(sd, MAPTYPE_BATTLEFIELD); if (hBG_enabled && map->list[sd->bl.m].flag.battleground) clif->map_property(sd, MAPPROPERTY_AGITZONE); return; } //Send charname_update every time you see someone in BG void clif_getareachar_unit_post(struct map_session_data *sd, struct block_list *bl) { if (bl->type == BL_PC) { struct map_session_data *tsd = BL_CAST(BL_PC, bl); clif->charnameupdate(tsd); return; } } void clif_parse_UseSkillToId_post(int fd, struct map_session_data *sd) { uint16 skill_id; /* uint16 skill_lv; */ int target_id; const struct s_packet_db *packet = clif->packet(RFIFOW(fd,0)); struct battleground_data *bgd; struct hBG_data *hBGd; if (!sd->bg_id) return; else if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return; /* skill_lv = RFIFOW(fd,packet->pos[0]); */ skill_id = RFIFOW(fd,packet->pos[1]); target_id = RFIFOL(fd,packet->pos[2]); if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX && hBGd->leader_char_id == sd->status.char_id) unit->skilluse_id(&sd->bl, target_id, skill_id, guild->checkskill(hBG_get_guild(sd->bg_id), skill_id)); } /** * Server tells 'sd' player client the abouts of 'dstsd' player */ void clif_getareachar_pc_post(struct map_session_data *sd,struct map_session_data *dstsd) { if (sd->bg_id && dstsd->bg_id && sd->bg_id == dstsd->bg_id) clif->hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); } /** * PC Post hooks */ void pc_update_idle_time_post(struct map_session_data* sd, enum e_battle_config_idletime type) { struct hBG_map_session_data *hBGsd = NULL; struct battleground_data *bgd = bg->team_search(sd->bg_id); struct hBG_data *hBGd = NULL; nullpo_retv(sd); if (bgd && (hBGd = getFromBGDATA(bgd, 0)) && (hBGsd = getFromMSD(sd, 1)) && hBGsd->state.afk) { char output[256]; /* Reset AFK status */ sprintf(output, "%s : %s is no longer AFK.", sd->status.name, hBGd->g->name); hBG_send_chat_message(bgd, sd->bl.id, sd->status.name, output, (int)strlen(output) + 1); hBGsd->state.afk = 0; } } bool pc_authok_post(bool ret, struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers) { if (sd) { WFIFOHEAD(chrif->fd, 14); WFIFOW(chrif->fd, 0) = PACKET_INTER_BG_STATS_REQ; WFIFOL(chrif->fd, 2) = sd->status.account_id; WFIFOL(chrif->fd, 6) = sd->status.char_id; WFIFOL(chrif->fd, 10) = sd->fd; WFIFOSET(chrif->fd, 14); } return ret; } /** * Character Interface Post-Hooks */ /** * Requests saving of hBG Statistics and sends data to char-server. * * @param sd pointer to map session data. * @param flag as an indicator to tell char-server if character is quitting. * @return boolean. */ bool chrif_save_post(bool ret, struct map_session_data *sd, int flag) { struct hBG_map_session_data *hBGsd = NULL; int len = 13 + sizeof(struct hBG_stats); nullpo_retr(false, sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return ret; if (flag == 1) // Logout from BG! Do not save anything. return ret; WFIFOHEAD(chrif->fd, len); WFIFOW(chrif->fd, 0) = PACKET_INTER_BG_STATS_SAVE; // 0x9000 Packet ID WFIFOL(chrif->fd, 2) = sd->status.account_id; // Account Id WFIFOL(chrif->fd, 6) = sd->status.char_id; // Char Id WFIFOB(chrif->fd, 12) = (flag==1); //Flag to tell char-server this character is quitting. memcpy(WFIFOP(chrif->fd, 13), &hBGsd->stats, sizeof(struct hBG_stats)); // hBG statistics. WFIFOSET(chrif->fd, len); return ret; } /** * Status Post Hooks */ int status_damage_post(int ret, struct block_list *src, struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) { struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; nullpo_retr(ret, target); if (src == NULL) return ret; if (src->type != BL_PC || (sd = BL_UCAST(BL_PC, src)) == NULL) return ret; if (map->list[src->m].flag.battleground == 0) return ret; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return ret; hBG_record_damage(src, target, (int) in_hp); return ret; } /** * Receives and allocates map session data with bg statistics * from char-server. * * @param fd as socket descriptor handle */ void hBG_statistics_parsefromchar(int fd) { struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_stats *stats = NULL; /* int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6); */ int char_fd = RFIFOL(fd,10); nullpo_retv(sockt->session[char_fd]); if ((sd = sockt->session[char_fd]->session_data) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) { CREATE(hBGsd, struct hBG_map_session_data, 1); addToMSD(sd, hBGsd, 1, false); } if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) memcpy(&hBGsd->stats, RFIFOP(fd, 14), sizeof(struct hBG_stats)); else memcpy(&hBGsd->stats, stats, sizeof(struct hBG_stats)); } /** * Battleground Interface Overload [lucaslsb] */ /** * Remove a player from a team. * @param sd pointer to session data. * @param flag type of leave. * @return Amount of player in the BG or 0 on failure. */ int bg_team_leave_overload(struct map_session_data *sd, enum bg_team_leave_type flag) { // Single Player leaves team int i; struct battleground_data *bgd; struct hBG_map_session_data *hBGsd; struct hBG_data *hBGd; struct map_session_data *pl_sd; struct guild *g; nullpo_ret(sd); if (!sd->bg_id) return 0; else if ((hBGsd = getFromMSD(sd, 1)) == NULL) return 0; else if ((bgd = bg->team_search(sd->bg_id)) == NULL) return 0; else if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return 0; // Packets hBG_send_dot_remove(sd); // Reset information. sd->bg_id = 0; hBGsd->bg_kills = 0; // Remove battleground items if any. hBG_member_remove_bg_items(sd); // Remove Guild Skill Buffs status_change_end(&sd->bl, SC_GUILDAURA, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_BATTLEORDER, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_REGENERATION, INVALID_TIMER); // Refresh Guild Information if (sd->status.guild_id && (g = guild->search(sd->status.guild_id)) != NULL) { clif->guild_belonginfo(sd, g); clif->guild_basicinfo(sd); clif->guild_allianceinfo(sd); clif->guild_memberlist(sd); clif->guild_skillinfo(sd); clif->guild_emblem(sd, g); } else { hBG_send_leave_single(sd, sd->status.name, "Leaving Battle..."); } clif->charnameupdate(sd); clif->guild_emblem_area(&sd->bl); ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == sd); if (i < MAX_BG_MEMBERS) // Removes member from BG memset(&bgd->members[i], 0, sizeof(struct battleground_member_data)); ARR_FIND(0, MAX_BG_MEMBERS, i, hBGd->g->member[i].sd == sd); if (i < MAX_BG_MEMBERS) // removes member from BG Guild memset(&hBGd->g->member[i].sd, 0, sizeof(hBGd->g->member[i].sd)); if (hBGd->leader_char_id == sd->status.char_id) hBGd->leader_char_id = 0; if (--bgd->count > 0) { for (i = 0; i < MAX_BG_MEMBERS; i++) { // Update other BG members if ((pl_sd = bgd->members[i].sd) == NULL) continue; if (!hBGd->leader_char_id) { // Set new Leader first on the list hBGd->leader_char_id = pl_sd->status.char_id; clif->charnameupdate(pl_sd); } switch (flag) { case 3: hBG_send_expulsion(pl_sd, sd->status.name, "Kicked by AFK Status..."); break; case 2: hBG_send_expulsion(pl_sd, sd->status.name, "Kicked by AFK Report..."); break; case 1: hBG_send_expulsion(pl_sd, sd->status.name, "User has quit the game..."); break; case 0: hBG_send_leave_single(pl_sd, sd->status.name, "Leaving Battle..."); break; } hBG_guild_window_info(pl_sd); hBG_send_emblem(pl_sd, hBGd->g); hBG_send_guild_member_list(pl_sd); } } if (bgd && strlen(bgd->logout_event) && flag) npc->event(sd, bgd->logout_event, 0); return bgd->count; } /** * Clif Interface Overload [lucaslsb] */ void clif_sendbgemblem_area_overload(struct map_session_data *sd) { int cmd = 0x2dd; const struct s_packet_db *packet = clif->packet(cmd); unsigned char buf[33]; nullpo_retv(sd); if (hBG_enabled) return; // Prevents display of conventional emblems WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->bl.id; safestrncpy((char*)WBUFP(buf, 6), sd->status.name, NAME_LENGTH); // name don't show in screen. WBUFW(buf, 30) = sd->bg_id; clif->send(buf, packet->len, &sd->bl, AREA); } void clif_sendbgemblem_single_overload(int fd, struct map_session_data *sd) { int cmd = 0x2dd; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (hBG_enabled) return; // Prevents display of conventional emblems WFIFOHEAD(fd, 32); WFIFOW(fd, 0) = cmd; WFIFOL(fd, 2) = sd->bl.id; safestrncpy(WFIFOP(fd, 6), sd->status.name, NAME_LENGTH); WFIFOW(fd, 30) = sd->bg_id; WFIFOSET(fd, packet->len); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Char Server Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Character Server Saving of hBG Statistics * * @param fd socket descriptor handle */ void char_bgstats_tosql(int fd) { struct hBG_stats pstats = {0}, *stats = NULL; int account_id = 0, char_id = 0; /* int flag = 0; */ nullpo_retv(sockt->session[fd]); account_id = RFIFOL(fd, 2); char_id = RFIFOL(fd, 6); /* flag = RFIFOB(fd, 12); */ if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) { CREATE(stats, struct hBG_stats, 1); addToSession(sockt->session[fd], stats, 0, true); } memcpy(&pstats, RFIFOP(fd, 13), sizeof(struct hBG_stats)); if (memcmp(stats, &pstats, sizeof(struct hBG_stats))) { if (SQL_ERROR == SQL->Query(inter->sql_handle, "REPLACE INTO `char_bg_stats` (" "`char_id`, " "`best_damage`, `total_damage_done`, `total_damage_received`, " "`ti_wins`, `ti_lost`, `ti_tie`, " "`eos_flags`, `eos_bases`, `eos_wins`, `eos_lost`, `eos_tie`, " "`boss_killed`, `boss_damage`, `boss_flags`, `boss_wins`, `boss_lost`, `boss_tie`, " "`dom_bases`, `dom_off_kills`, `dom_def_kills`, `dom_wins`, `dom_lost`, `dom_tie`, " "`td_kills`, `td_deaths`, `td_wins`, `td_lost`, `td_tie`, " "`sc_stolen`, `sc_captured`, `sc_dropped`, `sc_wins`, `sc_lost`, `sc_tie`, " "`ctf_taken`, `ctf_captured`, `ctf_dropped`, `ctf_wins`, `ctf_lost`, `ctf_tie`, " "`emperium_kills`, `barricade_kills`, `guardian_stone_kills`, `conquest_wins`, `conquest_losses`, " "`ru_captures`, `ru_wins`, `ru_lost`, `ru_skulls`," "`kill_count`, `death_count`, `wins`, `losses`, `ties`, `wins_as_leader`, `losses_as_leader`, `ties_as_leader`, `total_deserted`, `score`, `points`, `ranked_points`, `ranked_games`," "`sp_heal_potions`, `hp_heal_potions`, `yellow_gemstones`, `red_gemstones`, `blue_gemstones`, `poison_bottles`, `acid_demostration`, `acid_demostration_fail`, " "`support_skills_used`, `healing_done`, `wrong_support_skills_used`, `wrong_healing_done`, " "`sp_used`, `zeny_used`, `spiritb_used`, `ammo_used`)" " VALUES " "('%d'," "'%d','%u','%u'," "'%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%u','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%d','%d','%d'," "'%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d'," "'%u','%u','%u','%u','%u','%u','%u','%u'," "'%u','%u','%u','%u'," "'%u','%u','%u','%u')", char_id, pstats.best_damage, pstats.total_damage_done, pstats.total_damage_received, pstats.ti_wins,pstats.ti_lost,pstats.ti_tie, pstats.eos_flags,pstats.eos_bases,pstats.eos_wins,pstats.eos_lost,pstats.eos_tie, pstats.boss_killed,pstats.boss_damage,pstats.boss_flags,pstats.boss_wins,pstats.boss_lost,pstats.boss_tie, pstats.dom_bases,pstats.dom_off_kills,pstats.dom_def_kills,pstats.dom_wins,pstats.dom_lost,pstats.dom_tie, pstats.td_kills,pstats.td_deaths,pstats.td_wins,pstats.td_lost,pstats.td_tie, pstats.sc_stolen,pstats.sc_captured,pstats.sc_dropped,pstats.sc_wins,pstats.sc_lost,pstats.sc_tie, pstats.ctf_taken,pstats.ctf_captured,pstats.ctf_dropped,pstats.ctf_wins,pstats.ctf_lost,pstats.ctf_tie, pstats.emperium_kills,pstats.barricade_kills,pstats.guardian_stone_kills,pstats.conquest_wins,pstats.conquest_losses, pstats.ru_captures,pstats.ru_wins,pstats.ru_lost, pstats.ru_skulls, pstats.kill_count,pstats.death_count,pstats.wins,pstats.losses,pstats.ties,pstats.wins_as_leader,pstats.losses_as_leader, pstats.ties_as_leader,pstats.total_deserted,pstats.score,pstats.points,pstats.ranked_points,pstats.ranked_games, pstats.sp_heal_potions, pstats.hp_heal_potions, pstats.yellow_gemstones, pstats.red_gemstones, pstats.blue_gemstones, pstats.poison_bottles, pstats.acid_demostration, pstats.acid_demostration_fail, pstats.support_skills_used, pstats.healing_done, pstats.wrong_support_skills_used, pstats.wrong_healing_done, pstats.sp_used, pstats.zeny_used, pstats.spiritb_used, pstats.ammo_used)) { Sql_ShowDebug(inter->sql_handle); } else { memcpy(stats, &pstats, sizeof(struct hBG_stats)); ShowInfo("Saved char (AID/CID: %d/%d) - BG Statistics [by Smokexyz].\n", account_id, char_id); } } } void char_bgstats_fromsql(int fd) { struct hBG_stats temp_stats = { 0 }, *stats = NULL; int account_id = 0, char_id = 0, char_fd = 0, len = 0; struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle); if (stmt == NULL) { SqlStmt_ShowDebug(stmt); return; } account_id = RFIFOL(fd,2); char_id = RFIFOL(fd, 6); char_fd = RFIFOL(fd, 10); if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT " "`best_damage`,`total_damage_done`,`total_damage_received`,`ru_skulls`,`ti_wins`,`ti_lost`,`ti_tie`,`eos_flags`,`eos_bases`,`eos_wins`," // 0-9 "`eos_lost`,`eos_tie`,`boss_killed`,`boss_damage`,`boss_flags`,`boss_wins`,`boss_lost`,`boss_tie`,`td_kills`,`td_deaths`," //10-19 "`td_wins`,`td_lost`,`td_tie`,`sc_stolen`,`sc_captured`,`sc_dropped`,`sc_wins`,`sc_lost`,`sc_tie`,`ctf_taken`," //20-29 "`ctf_captured`,`ctf_dropped`,`ctf_wins`,`ctf_lost`,`ctf_tie`,`emperium_kills`,`barricade_kills`,`guardian_stone_kills`,`conquest_wins`,`conquest_losses`,"//30-39 "`kill_count`,`death_count`,`wins`,`losses`,`ties`,`wins_as_leader`,`losses_as_leader`,`ties_as_leader`,`total_deserted`,`score`,"//40-49 "`points`,`sp_heal_potions`,`hp_heal_potions`,`yellow_gemstones`,`red_gemstones`,`blue_gemstones`,`poison_bottles`,`acid_demostration`,`acid_demostration_fail`,`support_skills_used`,"//50-59 "`healing_done`,`wrong_support_skills_used`,`wrong_healing_done`,`sp_used`,`zeny_used`,`spiritb_used`,`ammo_used`,`ranked_points`,`ranked_games`,`ru_wins`,"//60-69 "`ru_lost`,`ru_captures`,`dom_bases`,`dom_off_kills`,`dom_def_kills`,`dom_wins`,`dom_lost`,`dom_tie`"//70-79 " FROM `char_bg_stats` WHERE `char_id` = ?") || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id) || SQL_ERROR == SQL->StmtExecute(stmt) || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_UINT, &temp_stats.best_damage, sizeof temp_stats.best_damage, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UINT, &temp_stats.total_damage_done, sizeof temp_stats.total_damage_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &temp_stats.total_damage_received, sizeof temp_stats.total_damage_received, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &temp_stats.ru_skulls, sizeof temp_stats.ru_skulls, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_USHORT, &temp_stats.ti_wins, sizeof temp_stats.ti_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_USHORT, &temp_stats.ti_lost, sizeof temp_stats.ti_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_USHORT, &temp_stats.ti_tie, sizeof temp_stats.ti_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_USHORT, &temp_stats.eos_flags, sizeof temp_stats.eos_flags, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_USHORT, &temp_stats.eos_bases, sizeof temp_stats.eos_bases, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_USHORT, &temp_stats.eos_wins, sizeof temp_stats.eos_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_USHORT, &temp_stats.eos_lost, sizeof temp_stats.eos_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_USHORT, &temp_stats.eos_tie, sizeof temp_stats.eos_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_USHORT, &temp_stats.boss_killed, sizeof temp_stats.boss_killed, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_UINT, &temp_stats.boss_damage, sizeof temp_stats.boss_damage, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_USHORT, &temp_stats.boss_flags, sizeof temp_stats.boss_flags, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_USHORT, &temp_stats.boss_wins, sizeof temp_stats.boss_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_USHORT, &temp_stats.boss_lost, sizeof temp_stats.boss_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_USHORT, &temp_stats.boss_tie, sizeof temp_stats.boss_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_USHORT, &temp_stats.td_kills, sizeof temp_stats.td_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_USHORT, &temp_stats.td_deaths, sizeof temp_stats.td_deaths, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_USHORT, &temp_stats.td_wins, sizeof temp_stats.td_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_USHORT, &temp_stats.td_lost, sizeof temp_stats.td_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_USHORT, &temp_stats.td_tie, sizeof temp_stats.td_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_USHORT, &temp_stats.sc_stolen, sizeof temp_stats.sc_stolen, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_USHORT, &temp_stats.sc_captured, sizeof temp_stats.sc_captured, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_USHORT, &temp_stats.sc_dropped, sizeof temp_stats.sc_dropped, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_USHORT, &temp_stats.sc_wins, sizeof temp_stats.sc_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_USHORT, &temp_stats.sc_lost, sizeof temp_stats.sc_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_USHORT, &temp_stats.sc_tie, sizeof temp_stats.sc_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_USHORT, &temp_stats.ctf_taken, sizeof temp_stats.ctf_taken, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_USHORT, &temp_stats.ctf_captured, sizeof temp_stats.ctf_captured, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_USHORT, &temp_stats.ctf_dropped, sizeof temp_stats.ctf_dropped, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_USHORT, &temp_stats.ctf_wins, sizeof temp_stats.ctf_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_USHORT, &temp_stats.ctf_lost, sizeof temp_stats.ctf_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_USHORT, &temp_stats.ctf_tie, sizeof temp_stats.ctf_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_USHORT, &temp_stats.emperium_kills, sizeof temp_stats.emperium_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_USHORT, &temp_stats.barricade_kills, sizeof temp_stats.barricade_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_USHORT, &temp_stats.guardian_stone_kills, sizeof temp_stats.guardian_stone_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_USHORT, &temp_stats.conquest_wins, sizeof temp_stats.conquest_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_USHORT, &temp_stats.conquest_losses, sizeof temp_stats.conquest_losses, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_USHORT, &temp_stats.kill_count, sizeof temp_stats.kill_count, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_USHORT, &temp_stats.death_count, sizeof temp_stats.death_count, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_USHORT, &temp_stats.wins, sizeof temp_stats.wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_USHORT, &temp_stats.losses, sizeof temp_stats.losses, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_USHORT, &temp_stats.ties, sizeof temp_stats.ties, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_USHORT, &temp_stats.wins_as_leader, sizeof temp_stats.wins_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_USHORT, &temp_stats.losses_as_leader, sizeof temp_stats.losses_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_USHORT, &temp_stats.ties_as_leader, sizeof temp_stats.ties_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_USHORT, &temp_stats.total_deserted, sizeof temp_stats.total_deserted, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_INT, &temp_stats.score, sizeof temp_stats.score, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_INT, &temp_stats.points, sizeof temp_stats.points, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_UINT, &temp_stats.sp_heal_potions, sizeof temp_stats.sp_heal_potions, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_UINT, &temp_stats.hp_heal_potions, sizeof temp_stats.hp_heal_potions, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &temp_stats.yellow_gemstones, sizeof temp_stats.yellow_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UINT, &temp_stats.red_gemstones, sizeof temp_stats.red_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &temp_stats.blue_gemstones, sizeof temp_stats.blue_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT, &temp_stats.poison_bottles, sizeof temp_stats.poison_bottles, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_UINT, &temp_stats.acid_demostration, sizeof temp_stats.acid_demostration, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UINT, &temp_stats.acid_demostration_fail, sizeof temp_stats.acid_demostration_fail, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 59, SQLDT_UINT, &temp_stats.support_skills_used, sizeof temp_stats.support_skills_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 60, SQLDT_UINT, &temp_stats.healing_done, sizeof temp_stats.healing_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 61, SQLDT_UINT, &temp_stats.wrong_support_skills_used, sizeof temp_stats.wrong_support_skills_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 62, SQLDT_UINT, &temp_stats.wrong_healing_done, sizeof temp_stats.wrong_healing_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 63, SQLDT_UINT, &temp_stats.sp_used, sizeof temp_stats.sp_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 64, SQLDT_UINT, &temp_stats.zeny_used, sizeof temp_stats.zeny_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 65, SQLDT_UINT, &temp_stats.spiritb_used, sizeof temp_stats.spiritb_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 66, SQLDT_UINT, &temp_stats.ammo_used, sizeof temp_stats.ammo_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 67, SQLDT_UINT, &temp_stats.ranked_points, sizeof temp_stats.ranked_points, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 68, SQLDT_USHORT, &temp_stats.ranked_games, sizeof temp_stats.ranked_games, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 69, SQLDT_USHORT, &temp_stats.ru_wins, sizeof temp_stats.ru_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 70, SQLDT_USHORT, &temp_stats.ru_lost, sizeof temp_stats.ru_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 71, SQLDT_USHORT, &temp_stats.ru_captures, sizeof temp_stats.ru_captures, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 72, SQLDT_USHORT, &temp_stats.dom_bases, sizeof temp_stats.dom_bases, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 73, SQLDT_USHORT, &temp_stats.dom_off_kills, sizeof temp_stats.dom_off_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 74, SQLDT_USHORT, &temp_stats.dom_def_kills, sizeof temp_stats.dom_def_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 75, SQLDT_USHORT, &temp_stats.dom_wins, sizeof temp_stats.dom_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 76, SQLDT_USHORT, &temp_stats.dom_lost, sizeof temp_stats.dom_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 77, SQLDT_USHORT, &temp_stats.dom_tie, sizeof temp_stats.dom_tie, NULL, NULL) || SQL_SUCCESS != SQL->StmtNextRow(stmt)) { temp_stats.score = 2000; } ShowInfo("Loaded char (AID/CID: %d/%d) - BG Statistics [by Smokexyz]\n", account_id, char_id); if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) { CREATE(stats, struct hBG_stats, 1); memcpy(stats, &temp_stats, sizeof(struct hBG_stats)); addToSession(sockt->session[fd], stats, 0, true); } else if (memcmp(stats, &temp_stats, sizeof(struct hBG_stats))) { memcpy(stats, &temp_stats, sizeof(struct hBG_stats)); } SQL->StmtFree(stmt); len = 14 + sizeof(struct hBG_stats); WFIFOHEAD(fd, len); WFIFOW(fd, 0) = PACKET_MAP_BG_STATS_GET; WFIFOL(fd, 2) = account_id; WFIFOL(fd, 6) = char_id; WFIFOL(fd, 10) = char_fd; memcpy(WFIFOP(fd, 14), &temp_stats, sizeof(struct hBG_stats)); WFIFOSET(fd, len); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Battle Configuration Parsing * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void hBG_config_read(const char *key, const char *val) { int value = config_switch (val); if (strcmpi(key,"battle_configuration/hBG_enabled") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_enabled, defaulting to 0.\n", value); return; } hBG_enabled = value; } else if (strcmpi(key, "battle_configuration/hBG_from_town_only") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_from_town_only, defaulting to 0.\n", value); return; } hBG_from_town_only = value; } else if (strcmpi(key, "battle_configuration/hBG_ip_check") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_ip_check, defaulting to 0.\n", value); return; } hBG_ip_check = value; } else if (strcmpi(key, "battle_configuration/hBG_idle_announce") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_idle_announce, defaulting to 60 seconds.\n", value); hBG_idle_announce = 60; } else { hBG_idle_announce = value; } } else if (strcmpi(key, "battle_configuration/hBG_idle_autokick") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_idle_autokick, defaulting to 5 minutes (300s).\n", value); hBG_idle_autokick = 300; } else { hBG_idle_autokick = value; } } else if (strcmpi(key, "battle_configuration/hBG_reportafk_leaderonly") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_reportafk_leaderonly, defaulting to 0.\n", value); hBG_reportafk_leaderonly = 0; } else { hBG_reportafk_leaderonly = value; } } else if (strcmpi(key, "battle_configuration/hBG_balanced_queue") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_balanced_queue, defaulting to 0.\n", value); return; } hBG_balanced_queue = value; } else if (strcmpi(key, "battle_configuration/hBG_reward_rates") == 0) { if (value < 0) { ShowWarning("Received invalid setting %d for hBG_reward_rates, defaulting to 100.\n", value); hBG_reward_rates = 100; } else { hBG_reward_rates = value; } } else if (strcmpi(key, "battle_configuration/hBG_xy_interval") == 0) { if (value < 1000) { ShowWarning("Received Invalid Setting %d for hBG_xy_interval. (min: %d, max: %d) Defaulting to 1000ms. \n", value, 1000, INT_MAX); hBG_xy_interval = 1000; } else { hBG_xy_interval = value; } } else if (strcmpi(key, "battle_configuration/hBG_ranked_mode") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_ranked_mode, defaulting to 0.\n", value); hBG_ranked_mode = 0; } else { hBG_ranked_mode = value; } } else if (strcmpi(key, "battle_configuration/hBG_leader_change") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_leader_change, defaulting to 0.\n", value); hBG_leader_change = 0; } else { hBG_leader_change = value; } } } int hBG_config_get(const char *key) { if (strcmpi(key, "battle_configuration/hBG_enabled") == 0) return hBG_enabled; else if (strcmpi(key, "battle_configuration/hBG_from_town_only") == 0) return hBG_from_town_only; else if (strcmpi(key, "battle_configuration/hBG_ip_check") == 0) return hBG_ip_check; else if (strcmpi(key, "battle_configuration/hBG_idle_announce") == 0) return hBG_idle_announce; else if (strcmpi(key, "battle_configuration/hBG_idle_autokick") == 0) return hBG_idle_autokick; else if (strcmpi(key, "battle_configuration/hBG_reportafk_leaderonly") == 0) return hBG_reportafk_leaderonly; else if (strcmpi(key, "battle_configuration/hBG_balanced_queue") == 0) return hBG_balanced_queue; else if (strcmpi(key, "battle_configuration/hBG_reward_rates") == 0) return hBG_reward_rates; else if (strcmpi(key, "battle_configuration/hBG_xy_interval") == 0) return hBG_xy_interval; else if (strcmpi(key, "battle_configuration/hBG_ranked_mode") == 0) return hBG_ranked_mode; else if (strcmpi(key, "battle_configuration/hBG_leader_change") == 0) return hBG_leader_change; return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Plugin Handling * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* run when server starts */ HPExport void plugin_init(void) { int interval = hBG_config_get("battle_configuration/hBG_xy_interval"); if (SERVER_TYPE == SERVER_TYPE_CHAR) { addPacket(PACKET_INTER_BG_STATS_REQ, 14, char_bgstats_fromsql, hpParse_FromMap); addPacket(PACKET_INTER_BG_STATS_SAVE, 13 + sizeof(struct hBG_stats), char_bgstats_tosql, hpParse_FromMap); } if (SERVER_TYPE == SERVER_TYPE_MAP) { addPacket(PACKET_MAP_BG_STATS_GET, 14+sizeof(struct hBG_stats), hBG_statistics_parsefromchar, hpChrif_Parse); /* Function Pre-Hooks */ addHookPre(npc, parse_unknown_mapflag, npc_parse_unknown_mapflag_pre); addHookPre(clif, charnameupdate, clif_charnameupdate_pre); addHookPre(clif, pGuildRequestInfo,clif_parse_GuildRequestInfo_pre); addHookPre(status, get_guild_id, status_get_guild_id_pre); addHookPre(status, get_emblem_id, status_get_emblem_id_pre); addHookPre(guild, isallied, guild_isallied_pre); addHookPre(skill, check_condition_castbegin, skill_check_condition_castbegin_pre); addHookPre(skill, not_ok, skillnotok_pre); addHookPre(skill, castend_nodamage_id, skill_castend_nodamage_id_pre); addHookPre(unit, free, unit_free_pre); /* Function Post-Hooks */ addHookPost(clif, pLoadEndAck, clif_parse_LoadEndAck_post); addHookPost(clif, pUseSkillToId, clif_parse_UseSkillToId_post); addHookPost(clif, getareachar_pc, clif_getareachar_pc_post); addHookPost(clif, getareachar_unit, clif_getareachar_unit_post); addHookPost(pc, update_idle_time, pc_update_idle_time_post); addHookPost(pc, authok, pc_authok_post); addHookPost(chrif, save, chrif_save_post); addHookPost(status, damage, status_damage_post); addHookPost(battle, check_target, battle_check_target_post); /* @Commands */ addAtcommand("bgrank", bgrank); addAtcommand("reportafk", reportafk); addAtcommand("leader", leader); /* Script Commands */ addScriptCommand("hBG_team_create","siiiss", hBG_team_create); addScriptCommand("hBG_queue_create","ss?", hBG_queue_create); addScriptCommand("hBG_queue_event","is", hBG_queue_event); addScriptCommand("hBG_queue_join","i", hBG_queue_join); addScriptCommand("hBG_queue_partyjoin","ii", hBG_queue_partyjoin); addScriptCommand("hBG_queue_leave","i", hBG_queue_leave); addScriptCommand("hBG_queue_data","ii", hBG_queue_data); addScriptCommand("hBG_queue2team","iisiiiss", hBG_queue2team); addScriptCommand("hBG_queue2team_single","iisii", hBG_queue2team_single); addScriptCommand("hBG_queue2teams","iiiiii*", hBG_queue2teams); addScriptCommand("hBG_queue_checkstart","iiii", hBG_queue_checkstart); addScriptCommand("hBG_balance_teams","iiiii*", hBG_balance_teams); addScriptCommand("hBG_waitingroom2bg","siiiss", hBG_waitingroom2bg); addScriptCommand("hBG_waitingroom2bg_single","isiis", hBG_waitingroom2bg_single); addScriptCommand("hBG_team_setxy","iii", hBG_team_setxy); addScriptCommand("hBG_team_reveal","i", hBG_team_reveal); addScriptCommand("hBG_team_conceal","i", hBG_team_conceal); addScriptCommand("hBG_team_setquest","ii", hBG_team_setquest); addScriptCommand("hBG_viewpointmap","siiiii", hBG_viewpointmap); addScriptCommand("hBG_monster_reveal","iii", hBG_monster_reveal); addScriptCommand("hBG_monster_set_team","ii", hBG_monster_set_team); addScriptCommand("hBG_monster_immunity","ii", hBG_monster_immunity); addScriptCommand("hBG_leave","", hBG_leave); addScriptCommand("hBG_destroy","i", hBG_destroy); addScriptCommand("hBG_clean","i", hBG_clean); addScriptCommand("hBG_get_data","ii", hBG_get_data); addScriptCommand("hBG_getareausers","isiiii", hBG_getareausers); addScriptCommand("hBG_updatescore","sii", hBG_updatescore); addScriptCommand("hBG_team_updatescore", "ii", hBG_update_score_team); addScriptCommand("hBG_team_guildid","i", hBG_get_team_gid); addScriptCommand("hBG_getitem","iii", hBG_getitem); addScriptCommand("hBG_getkafrapoints","ii", hBG_getkafrapoints); addScriptCommand("hBG_reward","iiiiisiii", hBG_reward); addScriptCommand("hBG_flooritem2xy", "siiii", hBG_flooritem2xy); addScriptCommand("hBG_warp", "isii", hBG_warp); hBG_queue_db = idb_alloc(DB_OPT_RELEASE_DATA); timer->add_func_list(hBG_send_xy_timer, "hBG_send_xy_timer"); timer->add_interval(timer->gettick() + interval , hBG_send_xy_timer, 0, 0, interval); } } /* triggered when server starts loading, before any server-specific data is set */ HPExport void server_preinit(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { addBattleConf("battle_configuration/hBG_enabled", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_from_town_only", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_ip_check", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_idle_announce", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_idle_autokick", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_balanced_queue", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_reward_rates", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_xy_interval", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_ranked_mode", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_leader_change", hBG_config_read, hBG_config_get, true); } } /* run when server is ready (online) */ HPExport void server_online(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { hBG_build_guild_data(); ShowStatus("%s v%s has been initialized. [by Smokexyz]\n", pinfo.name, pinfo.version); // clif interface overloading [lucaslsb] bg->team_leave = &bg_team_leave_overload; clif->sendbgemblem_area = &clif_sendbgemblem_area_overload; clif->sendbgemblem_single = &clif_sendbgemblem_single_overload; } } static int queue_db_final(union DBKey key, struct DBData *data, va_list ap) { struct hBG_queue_data *hBGqd = DB->data2ptr(data); if (hBGqd) hBG_queue_members_finalize(hBGqd); // Unlink all queue members return 0; } /* run when server is shutting down */ HPExport void plugin_final(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { hBG_queue_db->destroy(hBG_queue_db, queue_db_final); ShowInfo ("%s v%s has been finalized. [by Smokexyz]\n", pinfo.name, pinfo.version); } } hBG.c: In function ‘atcommand_reportafk’: hBG.c:2040:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘atcommand_leader’: hBG.c:2084:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘status_get_guild_id_pre’: hBG.c:3776:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)*bl)) > 0 ^ hBG.c: In function ‘status_get_emblem_id_pre’: hBG.c:3797:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)(*bl))) > 0 ^ PLUGIN hBG Using this plugin. Edited May 29, 2018 by AnnieRuru use [spoiler]+[code] tag when posting script > 10 lines Quote Share this post Link to post Share on other sites
0 Cabrera 10 Posted May 15, 2018 On 5/14/2018 at 9:04 PM, MikZ said: Good day! Help me how to correct these warnings please. Spoiler /* * This file is part of a Hercules Plugin library. * http://herc.ws - http://github.com/HerculesWS/Hercules * __ _ * / _\_ __ ___ ___ | | _______ ___ _ ____ * \ \| '_ ` _ \ / _ \| |/ / _ \ \/ / | | |_ / * _\ \ | | | | | (_) | < __/> <| |_| |/ / * \__/_| |_| |_|\___/|_|\_\___/_/\_\\__, /___| * |___/ * * Copyright (c) 2017 Smokexyz ([email protected]) * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License <http://www.gnu.org/licenses/> for * more details. * * * * * * * * * * * * * * * * * * * * * * * * * * Hercules Battlegrounds Plugin by [Smokexyz] * * * * * * * * * * * * * * * * * * * * * * * * */ #include "common/hercules.h" /* Should always be the first Hercules file included! */ #include "common/memmgr.h" #include "common/mmo.h" #include "common/socket.h" #include "common/strlib.h" #include "common/nullpo.h" #include "common/timer.h" #include "common/utils.h" #include "common/sql.h" #include "map/chrif.h" #include "map/atcommand.h" #include "map/clif.h" #include "map/pc.h" #include "map/script.h" #include "map/npc.h" #include "map/party.h" #include "map/mapreg.h" #include "map/guild.h" #include "map/chat.h" #include "map/quest.h" #include "map/mob.h" #include "map/map.h" #include "map/pet.h" #include "map/homunculus.h" #include "map/mercenary.h" #include "map/elemental.h" #include "map/skill.h" #include "map/battleground.h" #include "char/mapif.h" #include "char/inter.h" #include "plugins/HPMHooking.h" /* Hooking Macros */ #include "common/HPMDataCheck.h" /* should always be the last Hercules file included! */ #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Utility Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define add2limit(a, b, max) \ do { \ if ((max - a) < b) { \ a = max; \ } else { \ a += b; \ } \ } while(0) #define sub2limit(a, b, min) \ do { \ if ((b + min) > a) { \ a = min; \ } else { \ a -= b; \ } \ } while(0) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * HPM Structure Definition * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ HPExport struct hplugin_info pinfo = { "Hercules Battlegrounds", // Plugin name SERVER_TYPE_MAP | SERVER_TYPE_CHAR, // Server Type "1.0a", // Plugin version HPM_VERSION, // HPM Version (automatically updated) }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Global Variables * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define MAX_BATTLEGROUND_TEAMS 13 #define BLUE_SKULL 8965 #define RED_SKULL 8966 #define GREEN_SKULL 8967 /* Queue Database */ static struct DBMap* hBG_queue_db; /* Battleground Guild Storage */ struct guild bg_guild[MAX_BATTLEGROUND_TEAMS]; /* Battleground Guild Colors */ const unsigned int bg_colors[MAX_BATTLEGROUND_TEAMS] = { 0x0000FF, // Blue 0xFF0000, // Red 0x00FF00, // Green 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF }; /* Counter to check the next battleground ID */ static unsigned int bg_team_counter = 0; /* hBG Queue Counter */ static unsigned int hBG_queue_counter = 0; /** * Battle Configuration Variables */ int hBG_idle_announce, hBG_idle_autokick, hBG_reward_rates, hBG_ranked_mode, hBG_reportafk_leaderonly, hBG_balanced_queue, hBG_ip_check, hBG_from_town_only, hBG_enabled, hBG_xy_interval, hBG_leader_change; /** * BG Fame list types */ enum bg_fame_list_types { BG_NORMAL, BG_RANKED }; /** * Inter-server communication packet IDs. */ enum inter_packet_types { PACKET_INTER_BG_STATS_SAVE = 0x9000, PACKET_INTER_BG_STATS_REQ, PACKET_MAP_BG_STATS_GET, }; enum bg_mob_types { BARRICADE_ = 1906, OBJ_NEUTRAL = 1911, E_BAPHOMET2 = 2100, E_LORD_OF_DEATH2, E_DARK_LORD, E_KTULLANUX, E_DARK_SNAKE_LORD, E_TURTLE_GENERAL, E_APOCALIPS_H, E_FALLINGBISHOP, }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Structure Definitions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * BGD Structure Appendant */ struct hBG_data { time_t created_at; // Creation of this Team int leader_char_id; unsigned int color; // BG Guild Link struct guild *g; bool reveal_pos, reveal_pos2, reveal_flag; // Score Board int team_score; }; /** * hBG Queue Member Linked List */ struct hBG_queue_member { int position; struct map_session_data *sd; struct hBG_queue_member *next; }; struct hBG_stats { unsigned int best_damage, boss_damage, total_damage_done, total_damage_received; unsigned short // Triple Inferno ti_wins, ti_lost, ti_tie, // Tierra EoS eos_flags, eos_bases, eos_wins, eos_lost, eos_tie, // Tierra Bossnia boss_killed, boss_flags, boss_wins, boss_lost, boss_tie, // Tierra Domination dom_bases, dom_off_kills, dom_def_kills, dom_wins, dom_lost, dom_tie, // Flavius TD td_kills, td_deaths, td_wins, td_lost, td_tie, // Flavius SC sc_stolen, sc_captured, sc_dropped, sc_wins, sc_lost, sc_tie, // Flavius CTF ctf_taken, ctf_captured, ctf_dropped, ctf_wins, ctf_lost, ctf_tie, // Conquest emperium_kills, barricade_kills, guardian_stone_kills, conquest_wins, conquest_losses, // Rush ru_captures, ru_wins, ru_lost, ru_skulls; unsigned int // Ammo sp_heal_potions, hp_heal_potions, yellow_gemstones, red_gemstones, blue_gemstones, poison_bottles, acid_demostration, acid_demostration_fail, support_skills_used, healing_done, wrong_support_skills_used, wrong_healing_done, sp_used, zeny_used, spiritb_used, ammo_used; unsigned short kill_count, death_count, wins, losses, ties, wins_as_leader, losses_as_leader, ties_as_leader, total_deserted, ranked_games; int score, points, ranked_points; }; /** * MSD Structure Appendant (class 0) */ struct hBG_queue_data { unsigned int q_id, users, min_level; struct hBG_queue_member *first, *last; char queue_name[50], join_event[EVENT_NAME_LENGTH]; }; /** * MSD Structure Appendant (class 1) */ struct hBG_map_session_data { unsigned int bg_kills; struct { unsigned afk : 1; } state; struct hBG_stats stats; }; /** * MOBD Structure Appendant */ struct hBG_mob_data { struct { unsigned immunity: 1; } state; }; /** * MAPD Structure Appendant */ struct hBG_mapflag { unsigned hBG_topscore : 1; // No Detect NoMapFlag }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Function Forward Declarations * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int hBG_countlogin(struct map_session_data *sd, bool check_bat_room); int hBG_config_get(const char *key); struct guild* hBG_get_guild(int bg_id); struct map_session_data* hBG_getavailablesd(struct battleground_data *bgd); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Packet Sending Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Updates HP bar of a camp member. * Packet Ver < 20140613: 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W (ZC_BATTLEFIELD_NOTIFY_HP). * Packet Ver >= 20140613: 0a0e <account id>.L <hp>.L <max hp>.L (ZC_BATTLEFIELD_NOTIFY_HP2) * * @param sd map_session_data to send the packet to. * @return void. */ void hBG_send_hp_area(struct map_session_data *sd) { unsigned char buf[34]; // packet version can be wrong, // due to inconsistend data on other servers. #if PACKETVER < 20140613 const int cmd = 0x2e0; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->status.account_id; memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH); if (sd->battle_status.max_hp > INT16_MAX) { // To correctly display the %hp bar. [Skotlex] WBUFW(buf, 30) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); WBUFW(buf, 32) = 100; } else { WBUFW(buf, 30) = sd->battle_status.hp; WBUFW(buf, 32) = sd->battle_status.max_hp; } clif->send(buf, packet->len, &sd->bl, BG_AREA_WOS); #else const int cmd = 0xa0e; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->status.account_id; if (sd->battle_status.max_hp > INT32_MAX) { WBUFL(buf, 6) = sd->battle_status.hp / (sd->battle_status.max_hp / 100); WBUFL(buf, 10) = 100; } else { WBUFL(buf, 6) = sd->battle_status.hp; WBUFL(buf, 10) = sd->battle_status.max_hp; } clif->send(buf, packet->len, &sd->bl, BG_AREA_WOS); #endif } /** * Notify a singly client of HP change. * * @param fd socket fd to write * @param sd map_session_data containing information to be sent. */ void hBG_send_hp_single(int fd, struct map_session_data* sd) { const int cmd = 0x2e0; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WFIFOHEAD(fd, packet->len); WFIFOW(fd, 0) = cmd; WFIFOL(fd, 2) = sd->bl.id; memcpy(WFIFOP(fd,6),sd->status.name, NAME_LENGTH); if (sd->battle_status.max_hp > INT16_MAX) { WFIFOW(fd, 30) = sd->battle_status.hp/(sd->battle_status.max_hp/100); WFIFOW(fd, 32) = 100; } else { WFIFOW(fd, 30) = sd->battle_status.hp; WFIFOW(fd, 32) = sd->battle_status.max_hp; } WFIFOSET(fd, packet->len); } /** * Character Guild Name Information Packet * * @param sd map_session_data to send the packet to. * @return void */ void hBG_send_guild_info(struct map_session_data *sd) { int fd; int cmd = 0x16c; struct guild *g; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (!sd->bg_id || (g = hBG_get_guild(sd->bg_id)) == NULL || packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = 0x16c; WFIFOL(fd,2) = g->guild_id; WFIFOL(fd,6) = g->emblem_id; WFIFOL(fd,10) = 0; WFIFOB(fd,14) = 0; WFIFOL(fd,15) = 0; memcpy(WFIFOP(fd,19), g->name, NAME_LENGTH); WFIFOSET(fd, packet->len); } /** * Sends guild skills (ZC_GUILD_SKILLINFO). * 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B }* */ void hBG_send_guild_skillinfo(struct map_session_data* sd) { int fd; struct guild* g; int i,c; nullpo_retv(sd); if (!sd->bg_id || (g = hBG_get_guild(sd->bg_id)) == NULL) return; fd = sd->fd; WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37); WFIFOW(fd,0) = 0x0162; WFIFOW(fd,4) = g->skill_point; for (i = 0, c = 0; i < MAX_GUILDSKILL; i++) { if(g->skill[i].id > 0 && guild->check_skill_require(g, g->skill[i].id)) { int id = g->skill[i].id; int p = 6 + c*37; WFIFOW(fd,p+0) = id; WFIFOL(fd,p+2) = skill->get_inf(id); WFIFOW(fd,p+6) = g->skill[i].lv; if ( g->skill[i].lv) { WFIFOW(fd, p + 8) = skill->get_sp(id, g->skill[i].lv); WFIFOW(fd, p + 10) = skill->get_range(id, g->skill[i].lv); } else { WFIFOW(fd, p + 8) = 0; WFIFOW(fd, p + 10) = 0; } safestrncpy(WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; } } WFIFOW(fd,2) = 6 + c*37; WFIFOSET(fd,WFIFOW(fd,2)); } /** * Sends Guild Window Information * 01b6 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B <zeny>.L (ZC_GUILD_INFO2) * @param sd map_session_data to send the packet to. * @return void */ void hBG_guild_window_info(struct map_session_data *sd) { int fd; int cmd = 0x1b6; struct guild *g; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); fd = sd->fd; if ((g = hBG_get_guild(sd->bg_id)) == NULL || packet == NULL) return; WFIFOHEAD(fd, packet->len); // Hardcoded Length WFIFOW(fd, 0)= cmd; WFIFOL(fd, 2)= g->guild_id; WFIFOL(fd, 6)= g->guild_lv; WFIFOL(fd,10)= g->connect_member; WFIFOL(fd,14)= g->max_member; WFIFOL(fd,18)= g->average_lv; WFIFOL(fd,22)= (uint32)cap_value(g->exp,0,INT32_MAX); WFIFOL(fd,26)= g->next_exp; WFIFOL(fd,30)= 0; // Tax Points WFIFOL(fd,34)= 0; // Honor: (left) Vulgar [-100,100] Famed (right) WFIFOL(fd,38)= 0; // Virtue: (down) Wicked [-100,100] Righteous (up) WFIFOL(fd,42)= g->emblem_id; memcpy(WFIFOP(fd,46), g->name, NAME_LENGTH); memcpy(WFIFOP(fd,70), g->master, NAME_LENGTH); //safestrncpy(WFIFOP(fd,94), 0, 0); // "'N' castles" WFIFOL(fd, 110) = 0; // zeny WFIFOSET(fd, packet->len); } /** * Sends Guild Emblem to a player * @param sd map_session_data to send the packet to * @param g guild data * @return void */ void hBG_send_emblem(struct map_session_data *sd, struct guild *g) { int fd; nullpo_retv(sd); nullpo_retv(g); if (g->emblem_len <= 0) return; fd = sd->fd; WFIFOHEAD(fd, g->emblem_len+12); WFIFOW(fd,0) = 0x152; WFIFOW(fd,2) = g->emblem_len+12; WFIFOL(fd,4) = g->guild_id; WFIFOL(fd,8) = g->emblem_id; memcpy(WFIFOP(fd,12),g->emblem_data,g->emblem_len); WFIFOSET(fd, WFIFOW(fd,2)); } /** * Sends guild member list * @param sd map_session_data to send the packet to * @return void */ void hBG_send_guild_member_list(struct map_session_data *sd) { int fd, i, c; struct battleground_data *bgd; struct map_session_data *psd; struct hBG_data *hBGd; nullpo_retv(sd); if ((fd = sd->fd) == 0) return; if (!sd->bg_id || (bgd = bg->team_search(sd->bg_id)) == NULL) return; else if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return; WFIFOHEAD(fd, bgd->count * 104 + 4); WFIFOW(fd, 0) = 0x154; for (i = 0, c = 0; i < bgd->count; i++) { struct hBG_map_session_data *hBGsd; if ((psd = bgd->members[i].sd) == NULL) continue; if ((hBGsd = getFromMSD(psd, 1)) == NULL) continue; WFIFOL(fd,c*104+ 4) = psd->status.account_id; WFIFOL(fd,c*104+ 8) = psd->status.char_id; WFIFOW(fd,c*104+12) = psd->status.hair; WFIFOW(fd,c*104+14) = psd->status.hair_color; WFIFOW(fd,c*104+16) = psd->status.sex; WFIFOW(fd,c*104+18) = psd->status.class; WFIFOW(fd,c*104+20) = psd->status.base_level; WFIFOL(fd,c*104+22) = hBGsd->bg_kills; // Exp slot used to show kills WFIFOL(fd,c*104+26) = 1; // Online WFIFOL(fd,c*104+30) = hBGd->leader_char_id == psd->status.char_id ? 0 : 1; // Position memset(WFIFOP(fd,c*104+34),0,50); // Position Name memcpy(WFIFOP(fd,c*104+84),psd->status.name,NAME_LENGTH); // Player Name c++; } WFIFOW(fd, 2)=c*104+4; WFIFOSET(fd,WFIFOW(fd,2)); } /** * Send guild leave packet * @param sd map_session_data to send the packet to * @param *name contains name of the character. * @param *mes contains leave message from player. * @return void */ void hBG_send_leave_single(struct map_session_data *sd, const char *name, const char *mes) { unsigned char buf[128]; int cmd = 0x15a; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; WBUFW(buf, 0) = cmd; memcpy(WBUFP(buf, 2), name, NAME_LENGTH); memcpy(WBUFP(buf,26), mes, 40); clif->send(buf, packet->len, &sd->bl, SELF); } /** * Notifies clients of a battleground message ZC_BATTLEFIELD_CHAT * 02dc <packet len>.W <account id>.L <name>.24B <message>.?B * * @param bgd battleground_data to send the message to * @param src_id id of the source of the message. * @param name contains the name of the character. * @param mes contains the message to be sent. * @param len contains the length of the message. * @return void. */ void hBG_send_chat_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, int len) { struct map_session_data *sd; unsigned char *buf; nullpo_retv(bgd); nullpo_retv(name); nullpo_retv(mes); if ((sd = hBG_getavailablesd(bgd)) == NULL) return; len = (int)strlen(mes); Assert_retv(len <= INT16_MAX - NAME_LENGTH - 8); buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char)); WBUFW(buf, 0) = 0x2dc; WBUFW(buf, 2) = len + NAME_LENGTH + 8; WBUFL(buf, 4) = src_id; memcpy(WBUFP(buf, 8), name, NAME_LENGTH); memcpy(WBUFP(buf, 32), mes, len); // [!] no NULL terminator clif->send(buf, WBUFW(buf, 2), &sd->bl, BG); if (buf) aFree(buf); } /** * Notifies the client of a guild expulsion. * * @param sd map_session_data to send the packet to * @param *name contains the name of the character. * @param *mes contains the expulsion message. */ void hBG_send_expulsion(struct map_session_data *sd, const char *name, const char *mes) { int fd; int cmd = 0x15c; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = cmd; safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); safestrncpy((char*)WFIFOP(fd,26), mes, 40); safestrncpy((char*)WFIFOP(fd,66), "", NAME_LENGTH); WFIFOSET(fd, packet->len); } /** * Notifies a single client of BG score updates * * @param sd map_session_data to send the packet to * @return void */ void hBG_update_score_single(struct map_session_data *sd) { int fd; int cmd = 0x2de; struct battleground_data *bgd; struct hBG_data *hBGd; struct hBG_mapflag *hBG_mf = getFromMAPD(&map->list[sd->bl.m], 0); const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (packet == NULL) return; fd = sd->fd; WFIFOHEAD(fd, packet->len); WFIFOW(fd,0) = cmd; if (map->list[sd->bl.m].flag.battleground == 2) { // Score Board on Map. Team vs Team WFIFOW(fd,2) = map->list[sd->bl.m].bgscore_lion; WFIFOW(fd,4) = map->list[sd->bl.m].bgscore_eagle; } else if (map->list[sd->bl.m].flag.battleground == 3 && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) { // Score Board Multiple. Team vs Best Score WFIFOW(fd,2) = hBGd->team_score; WFIFOL(fd,4) = hBG_mf->hBG_topscore; } WFIFOSET(fd, packet->len); } /** * Notifies all clients in a Battleground Team * * @param bgd battleground_data containing the map_session_datas to send the packet to * @return void */ void hBG_update_score_team(struct battleground_data *bgd) { unsigned char buf[6]; struct map_session_data *sd; int i, m, cmd = 0x2de; struct hBG_data *hBGd = getFromBGDATA(bgd, 0); struct hBG_mapflag *hBG_mf; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(bg); if ((m = map->mapindex2mapid(bgd->mapindex)) < 0 || hBGd == NULL || (hBG_mf = getFromMAPD(&map->list[m], 0)) == NULL || packet == NULL) return; WBUFW(buf,0) = cmd; WBUFW(buf,2) = hBGd->team_score; WBUFW(buf,4) = hBG_mf->hBG_topscore; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL || sd->bl.m != m) continue; clif->send(buf, packet->len, &sd->bl, SELF); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Queue System Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Searches hBG_queue_db by q_id * @param q_id contains the id of the queue to be searched. * @return hBG_queue_data * pointer to the memory location or null if not found. */ struct hBG_queue_data* hBG_queue_search(int q_id) { // Search a Queue using q_id if (!q_id) return NULL; return (struct hBG_queue_data *) idb_get(hBG_queue_db, q_id); } /** * Creates a Queue * @param queue_name contains the name of the queue. * @param join_event contains the event run on joining the queue. * @param min_level contains the minimum level to be able to join. * @return queue_id id of the queue created. */ int hBG_queue_create(const char* queue_name, const char* join_event, int min_level) { struct hBG_queue_data *hBGqd; if (++hBG_queue_counter <= 0) hBG_queue_counter = 1; CREATE(hBGqd, struct hBG_queue_data, 1); hBGqd->q_id = hBG_queue_counter; safestrncpy(hBGqd->queue_name, queue_name, sizeof(hBGqd->queue_name)); safestrncpy(hBGqd->join_event, join_event, sizeof(hBGqd->join_event)); hBGqd->first = hBGqd->last = NULL; // First and Last Queue Members hBGqd->users = 0; hBGqd->min_level = min_level; idb_put(hBG_queue_db, hBG_queue_counter, hBGqd); return hBGqd->q_id; } /** * Remove all queue members from the queue and free the links. * @param hBGqd pointer to the queue data. * @return void. */ void hBG_queue_members_finalize(struct hBG_queue_data *hBGqd) { struct hBG_queue_member *head, *next; nullpo_retv(hBGqd); head = hBGqd->first; while (head) { next = head->next; aFree(head); head = next; } hBGqd->first = hBGqd->last = NULL; hBGqd->users = 0; } /** * Add a player to the queue. * @param hBGqd pointer to the queue data. * @param sd player to be added to the queue. * @return postition of the player in queue. */ int hBG_queue_member_add(struct hBG_queue_data *hBGqd, struct map_session_data *sd) { struct hBG_queue_member *hBGqm; nullpo_retr(0, hBGqd); nullpo_retr(0, sd); hBGqd->users++; CREATE(hBGqm, struct hBG_queue_member, 1); hBGqm->sd = sd; hBGqm->position = hBGqd->users; hBGqm->next = NULL; if (getFromMSD (sd, 0) == NULL) addToMSD(sd, hBGqd, 0, false); if (hBGqd->last == NULL) { hBGqd->first = hBGqd->last = hBGqm; // Attach to first position } else { // Attach at the end of the queue hBGqd->last->next = hBGqm; hBGqd->last = hBGqm; } return hBGqm->position; } /** * Get a member of the queue from position n. * @param hBGqd pointer to the queue data * @param position position of the player in queue * @return queue_member data or NULL if not found. */ struct hBG_queue_member* hBG_queue_member_get(struct hBG_queue_data *hBGqd, int position) { struct hBG_queue_member *head; if (!hBGqd) return NULL; head = hBGqd->first; while (head != NULL) { if (head->sd && head->position == position) return head; head = head->next; } return NULL; } /** * Clear a queue and remove from memory. * @param hBGqd pointer to queue_data * return 1 on success, 0 on failure. */ int hBG_queue_destroy(struct hBG_queue_data *hBGqd) { nullpo_ret(hBGqd); hBG_queue_members_finalize(hBGqd); idb_remove(hBG_queue_db, hBGqd->q_id); return 1; } /** * Remove a member from a queue * @param hBGqd pointer to queue data. * @param id block list ID of player in queue. * @return position of a player in the queue or 0 if not found. */ int hBG_queue_member_remove(struct hBG_queue_data *hBGqd, int id) { struct hBG_queue_member *head, *previous; int i; nullpo_retr(0, hBGqd); head = hBGqd->first; previous = NULL; while (head != NULL) { if (head->sd && head->sd->bl.id == id) { struct hBG_queue_member *next; next = head->next; i = head->position; hBGqd->users--; // De-attach target from the main queue if (previous) { previous->next = head->next; } else { hBGqd->first = head->next; // Deleted is on first position } if (head->next == NULL) hBGqd->last = previous; // Deleted is on last position while (next != NULL) { next->position--; // Decrement positions of the next in queue. next = next->next; } aFree(head); return i; } previous = head; head = head->next; } return 0; } /** * Search a member in the queue by Block List ID. * @param hBGqd pointer to queue data. * @param id block list ID of a player in queue. * @return position of a player in the queue or 0 if not found. */ int hBG_queue_member_search(struct hBG_queue_data *hBGqd, int id) { struct hBG_queue_member *head; nullpo_retr(0,hBGqd); head = hBGqd->first; while (head != NULL) { if (head->sd && head->sd->bl.id == id) return head->position; head = head->next; } return 0; // Not Found } /** * Add a player to the queue. * @param sd pointer to player to be added in queue. * @param q_id ID of the queue to be appended. * @return 0 on failure, 1 on success. */ int hBG_queue_join(struct map_session_data *sd, int q_id) { char output[128]; struct hBG_queue_data *hBGqd; int i = 0; int login_ip_count = hBG_config_get("battle_configuration/hBG_ip_check"); nullpo_ret(sd); if (hBG_config_get("battle_configuration/hBG_from_town_only") && map->list[sd->bl.m].flag.town == 0) { clif->message(sd->fd,"You only can join BG queues from Towns or BG Waiting Room."); return 0; } else if (sd->bg_id) { clif->message(sd->fd,"You cannot join queues when already playing Battlegrounds."); return 0; } else if (sd->sc.data[SC_JAILED]) { clif->message(sd->fd,"You cannot join queues when jailed."); return 0; } // Get Queue by ID if ((hBGqd = hBG_queue_search(q_id)) == NULL) { return 0; // Current Queue don't exists } else if ((i = hBG_queue_member_search(hBGqd, sd->bl.id))) { // You cannot join a Queue if you are already in one. sprintf(output, "You are already in %s queue at position %d.", hBGqd->queue_name, i); clif->message(sd->fd, output); return 0; } else if (hBGqd && hBGqd->min_level && sd->status.base_level < hBGqd->min_level) { sprintf(output,"You cannot join %s queue. Required min level is %ud.", hBGqd->queue_name, hBGqd->min_level); clif->message(sd->fd,output); return 0; } else if (login_ip_count && hBG_countlogin(sd,false) > login_ip_count) { sprintf(output,"You cannot join %s queue. A max of %d characters are using your IP address.", hBGqd->queue_name, login_ip_count); clif->message(sd->fd,output); return 0; } i = hBG_queue_member_add(hBGqd, sd); sprintf(output,"You have joined %s queue at position %d.", hBGqd->queue_name, i); clif->message(sd->fd,output); if (hBGqd->join_event[0]) npc->event_do(hBGqd->join_event); return i; } /** * Process player leaving a queue. * @param sd pointer to player leaving the queue. * @param q_id ID of the queue to be left. * @return 0 on failure, 1 on success. */ int hBG_queue_leave(struct map_session_data *sd, int q_id) { char output[128]; struct hBG_queue_data *qd; if ((qd = hBG_queue_search(q_id)) == NULL) return 0; if (!hBG_queue_member_remove(qd,sd->bl.id)) { sprintf(output,"You are not in the %s queue.", qd->queue_name); clif->message(sd->fd,output); return 0; } sprintf(output, "You have been removed from the %s queue.", qd->queue_name); clif->message(sd->fd, output); return 1; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Battleground Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Return any available player in a Battleground * @param bgd pointer to battleground queue. * @return map_session_data *sd pointer to player data or NULL if not found. */ struct map_session_data* hBG_getavailablesd(struct battleground_data *bgd) { int i; nullpo_retr(NULL, bgd); ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd != NULL); return(i < MAX_BG_MEMBERS) ? bgd->members[i].sd : NULL; } /** * Count the number of players with the same IP in battlegrounds. * @param sd pointer to map session data. * @param check_bat_room boolean to include checks in bat_room. * @return amount of accounts online. */ int hBG_countlogin(struct map_session_data *sd, bool check_bat_room) { int c = 0, m = map->mapname2mapid("bat_room"); struct map_session_data* pl_sd; struct s_mapiterator* iter; nullpo_ret(sd); iter = mapit_getallusers(); for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) { if (!(getFromMSD(sd, 0) || map->list[pl_sd->bl.m].flag.battleground || (check_bat_room && pl_sd->bl.m == m))) continue; if (sockt->session[sd->fd]->client_addr == sockt->session[pl_sd->fd]->client_addr) c++; } mapit->free(iter); return c; } /** * Performs initialization tasks on new battlegrounds. * @param m map Index * @param rx respawn X co-ordinate * @param ry respawn Y co-ordinate * @param guild_index Index of the BG guild to be used * @param *ev NPC Script event to be called when player logs out. * @param *dev NPC Script event to be called when player dies. * @return ID of the battleground. */ int hBG_create(unsigned short m, short rx, short ry, int guild_index, const char *ev, const char *dev) { struct battleground_data *bgd; struct hBG_data *hBGd; CREATE(bgd, struct battleground_data, 1); CREATE(hBGd, struct hBG_data, 1); if (++bg_team_counter <= 0) bg_team_counter = 1; bgd->bg_id = bg_team_counter; bgd->count = 0; bgd->mapindex = m; bgd->x = rx; bgd->y = ry; safestrncpy(bgd->logout_event, ev, sizeof(bgd->logout_event)); safestrncpy(bgd->die_event, dev, sizeof(bgd->die_event)); memset(&bgd->members, 0, sizeof(bgd->members)); hBGd->color = bg_colors[guild_index]; hBGd->created_at = 0; hBGd->g = &bg_guild[guild_index]; addToBGDATA(bgd, hBGd, 0, true); idb_put(bg->team_db, bg_team_counter, bgd); return bgd->bg_id; } /** * Add a player to the Battleground Team * @param bg_id Id of the battleground * @param sd pointer to the player's session data. * @return 0 on failure, 1 on success. */ int hBG_team_join(int bg_id, struct map_session_data *sd) { // Player joins team int i; struct battleground_data *bgd = bg->team_search(bg_id); struct map_session_data *pl_sd; struct hBG_map_session_data *hBGsd; struct hBG_data *hBGd; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL || sd == NULL || sd->bg_id) return 0; ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == NULL); if (i == MAX_BG_MEMBERS) return 0; // No free slots // Handle Additional Map Session BG data if ((hBGsd = getFromMSD(sd, 1)) == NULL) { CREATE(hBGsd, struct hBG_map_session_data, 1); addToMSD(sd, hBGsd, 1, false); } hBGsd->bg_kills = 0; hBGsd->state.afk = 0; // Update player's idle item. pc->update_idle_time(sd, BCIDLE_WALK); sd->bg_id = bg_id; // Battleground Member data bgd->members[i].sd = sd; bgd->members[i].x = sd->bl.x; bgd->members[i].y = sd->bl.y; bgd->count++; // Guild Member Data simulation hBGd->g->member[i].sd = sd; // Creation Tick = First member joined. if (hBGd->created_at == 0) hBGd->created_at = sockt->last_tick; // First Join = Team Leader if (hBGd->leader_char_id == 0) hBGd->leader_char_id = sd->status.char_id; guild->send_dot_remove(sd); hBG_send_guild_info(sd); // Send Guild Name/Emblem under character clif->charnameupdate(sd); // Update character's nameplate for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((pl_sd = bgd->members[i].sd) == NULL) continue; // Simulate Guild Information hBG_guild_window_info(pl_sd); // Main Guild window information. hBG_send_emblem(pl_sd, hBGd->g); // Emblems hBG_send_guild_member_list(pl_sd); // Member list hBG_send_guild_skillinfo(sd); // Send Guild skill information. if (pl_sd != sd) hBG_send_hp_single(sd->fd,pl_sd); } clif->guild_emblem_area(&sd->bl); clif->bg_hp(sd); clif->bg_xy(sd); return 1; } /** * Reveal a player's position to another player. * @param bl pointer to block list. * @param ap list of arguments * @return 0. */ int hBG_reveal_pos(struct block_list *bl, va_list ap) { struct map_session_data *pl_sd, *sd = NULL; int flag, color; pl_sd = (struct map_session_data *)bl; sd = va_arg(ap,struct map_session_data *); // Source flag = va_arg(ap,int); color = va_arg(ap,int); if (pl_sd->bg_id == sd->bg_id) return 0; // Same Team clif->viewpoint(pl_sd,sd->bl.id,flag,sd->bl.x,sd->bl.y,sd->bl.id,color); return 0; } /** * Remove minimap indicator for player. * @param sd pointer to session data. * @return 0 */ int hBG_send_dot_remove(struct map_session_data *sd) { struct battleground_data *bgd; struct hBG_data *hBGd; int m; if (sd && sd->bg_id && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) { clif->bg_xy_remove(sd); if (hBGd->reveal_pos && (m = map->mapindex2mapid(bgd->mapindex)) == sd->bl.m) map->foreachinmap(hBG_reveal_pos, m,BL_PC,sd,2,0xFFFFFF); } return 0; } /** * Searches and removes battleground game specific * items from the player's inventory. * @param sd as struct map_session_data */ void hBG_member_remove_bg_items(struct map_session_data *sd) { int n; nullpo_retv(sd); if ((n = pc->search_inventory(sd,BLUE_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2, LOG_TYPE_CONSUME); if ((n = pc->search_inventory(sd,RED_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2,LOG_TYPE_CONSUME); if ((n = pc->search_inventory(sd,GREEN_SKULL)) >= 0) pc->delitem(sd, n, sd->status.inventory[n].amount, 0, 2,LOG_TYPE_CONSUME); } /** * Get guild data of the Battleground * @param bg_id ID of the battleground * @return guild of the battleground or NULL. */ struct guild* hBG_get_guild(int bg_id) { struct battleground_data *bgd = bg->team_search(bg_id); struct hBG_data *hBGd; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return NULL; return hBGd->g; } /** * Remove all members from a BG Team. * @param bg_id ID of the battleground. * @param remove Boolean for removal of BG from team_db. * @return 0 on failure, 1 on success. */ int hBG_team_finalize(int bg_id, bool remove) { // Deletes BG Team from db int i; struct map_session_data *sd; struct battleground_data *bgd = bg->team_search(bg_id); struct hBG_data *hBGd; struct guild *g; if (bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return 0; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; hBG_send_dot_remove(sd); sd->bg_id = 0; // Remove Guild Skill Buffs status_change_end(&sd->bl, SC_GUILDAURA, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_BATTLEORDER, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_REGENERATION, INVALID_TIMER); if (sd->status.guild_id && (g = guild->search(sd->status.guild_id)) != NULL) { clif->guild_belonginfo(sd,g); clif->guild_basicinfo(sd); clif->guild_allianceinfo(sd); clif->guild_memberlist(sd); clif->guild_skillinfo(sd); } else { hBG_send_leave_single(sd, sd->status.name, "Leaving Battle..."); } clif->charnameupdate(sd); clif->guild_emblem_area(&sd->bl); } if (remove) { idb_remove(bg->team_db, bg_id); } else { bgd->count = 0; hBGd->leader_char_id = 0; hBGd->team_score = 0; hBGd->created_at = 0; memset(&bgd->members, 0, sizeof(bgd->members)); } return 1; } /** * Give items to the Battleground Team. * @param bg_id ID of the battleground. * @param nameid ID of the item. * @param amount Amount of the Item to be given. * @return void; */ void hBG_team_getitem(int bg_id, int nameid, int amount) { struct battleground_data *bgd; struct map_session_data *sd; struct item_data *id; struct item it; int reward_rate = hBG_config_get("battle_configuration/bg_reward_rates"); int get_amount, j, flag; if (amount < 1 || (bgd = bg->team_search(bg_id)) == NULL || (id = itemdb->exists(nameid)) == NULL) return; if (nameid != 7828 && nameid != 7829 && nameid != 7773) return; if (reward_rate != 100) amount = amount * reward_rate / 100; memset(&it, 0, sizeof(it)); it.nameid = nameid; it.identify = 1; for (j = 0; j < MAX_BG_MEMBERS; j++) { if ((sd = bgd->members[j].sd) == NULL) continue; get_amount = amount; if ((flag = pc->additem(sd,&it,get_amount,LOG_TYPE_SCRIPT))) clif->additem(sd,0,0,flag); } } /** * Give kafra points to the team. * @param bg_id ID of the battleground. * @param amount Amount of kafra points to be given. */ void hBG_team_get_kafrapoints(int bg_id, int amount) { struct battleground_data *bgd; struct map_session_data *sd; int i, get_amount, reward_rate = hBG_config_get("battle_configuration/bg_reward_rates"); if ((bgd = bg->team_search(bg_id)) == NULL) return; if (reward_rate != 100) amount = amount * reward_rate/ 100; for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; get_amount = amount; pc->getcash(sd,0,get_amount); } } void hBG_add_rank_points(struct map_session_data *sd, int ranktype, int count) { struct hBG_map_session_data *hBGsd; char message[100]; nullpo_retv(sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; if (ranktype == BG_RANKED) { add2limit(hBGsd->stats.ranked_points, count, MAX_FAME); sprintf(message, "[Battlegrounds Ranked] Your ranking has increased by %d.", count); clif->disp_message(&sd->bl, message, SELF); hookStop(); } else if (ranktype == BG_NORMAL) { add2limit(hBGsd->stats.points, count, MAX_FAME); sprintf(message, "[Battlegrounds Normal] Your ranking has increased by %d.", count); clif->disp_message(&sd->bl, message, SELF); hookStop(); } } /* ============================================================== bg_arena (0 EoS | 1 Boss | 2 TI | 3 CTF | 4 TD | 5 SC | 6 CON | 7 RUSH | 8 DOM) bg_result (0 Won | 1 Tie | 2 Lost) ============================================================== */ void hBG_team_rewards(int bg_id, int nameid, int amount, int kafrapoints, int quest_id, const char *var, int add_value, int bg_arena, int bg_result) { struct battleground_data *bgd = NULL; struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_data *hBGd = NULL; struct item_data *id; struct item it; int j, flag, get_amount, reward_rate = hBG_config_get("battle_configuration/hBG_reward_rates"), fame = 0, type = 0; if (amount < 1 || (bgd = bg->team_search(bg_id)) == NULL || (id = itemdb->exists(nameid)) == NULL) return; if (reward_rate != 100) { // BG Reward Rates amount = amount * reward_rate / 100; kafrapoints = kafrapoints * reward_rate / 100; } memset(&it,0,sizeof(it)); bg_result = cap_value(bg_result, 0, 2); if (nameid == 7828 || nameid == 7829 || nameid == 7773) { it.nameid = nameid; it.identify = 1; } else { nameid = 0; } for (j = 0; j < MAX_BG_MEMBERS; j++) { if ((sd = bgd->members[j].sd) == NULL) continue; else if ((hBGsd = getFromMSD(sd, 1)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) continue; if (quest_id) quest->add(sd, quest_id, 0); pc_setglobalreg(sd, script->add_str(var), pc_readglobalreg(sd,script->add_str(var)) + add_value); if (kafrapoints > 0) { get_amount = kafrapoints; pc->getcash(sd,0,get_amount); } if (nameid && amount > 0) { get_amount = amount; if ((flag = pc->additem(sd,&it,get_amount,LOG_TYPE_SCRIPT))) clif->additem(sd,0,0,flag); } type = hBG_config_get("battle_configuration/hBG_ranked_mode")?BG_RANKED:BG_NORMAL; switch (bg_result) { case 0: // Won add2limit(hBGsd->stats.wins,1,USHRT_MAX); fame = 100; if (sd->status.char_id == hBGd->leader_char_id) { add2limit(hBGsd->stats.wins_as_leader,1,USHRT_MAX); fame += 25; } hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_wins,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_wins,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_wins,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_wins,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_wins,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_wins,1,USHRT_MAX); break; case 6: add2limit(hBGsd->stats.conquest_wins,1,USHRT_MAX); break; case 7: add2limit(hBGsd->stats.ru_wins,1,USHRT_MAX); break; case 8: add2limit(hBGsd->stats.dom_wins,1,USHRT_MAX); break; } break; case 1: // Tie add2limit(hBGsd->stats.ties,1,USHRT_MAX); fame = 75; if (sd->status.char_id == hBGd->leader_char_id) { add2limit(hBGsd->stats.ties_as_leader,1,USHRT_MAX); fame += 10; } hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_tie,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_tie,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_tie,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_tie,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_tie,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_tie,1,USHRT_MAX); break; // No Tie for Conquest or Rush case 8: add2limit(hBGsd->stats.dom_tie,1,USHRT_MAX); break; } break; case 2: // Lost add2limit(hBGsd->stats.losses,1,USHRT_MAX); fame = 50; if (sd->status.char_id == hBGd->leader_char_id) add2limit(hBGsd->stats.losses_as_leader,1,USHRT_MAX); hBG_add_rank_points(sd, fame, type); switch (bg_arena) { case 0: add2limit(hBGsd->stats.eos_lost,1,USHRT_MAX); break; case 1: add2limit(hBGsd->stats.boss_lost,1,USHRT_MAX); break; case 2: add2limit(hBGsd->stats.ti_lost,1,USHRT_MAX); break; case 3: add2limit(hBGsd->stats.ctf_lost,1,USHRT_MAX); break; case 4: add2limit(hBGsd->stats.td_lost,1,USHRT_MAX); break; case 5: add2limit(hBGsd->stats.sc_lost,1,USHRT_MAX); break; case 6: add2limit(hBGsd->stats.conquest_losses,1,USHRT_MAX); break; case 7: add2limit(hBGsd->stats.ru_lost,1,USHRT_MAX); break; case 8: add2limit(hBGsd->stats.dom_lost,1,USHRT_MAX); break; } break; } } } /** * Build BG Guild Emulation data. * @params (void) * @return void. */ void hBG_build_guild_data(void) { int i, j, k, gskill; memset(&bg_guild, 0, sizeof(bg_guild)); for (i = 1; i <= MAX_BATTLEGROUND_TEAMS; i++) { // Emblem Data - Guild ID's FILE* fp = NULL; char gpath[256]; j = i - 1; bg_guild[j].emblem_id = 1; // Emblem Index bg_guild[j].guild_id = SHRT_MAX - j; bg_guild[j].guild_lv = 1; bg_guild[j].max_member = MAX_BG_MEMBERS; // Skills if (j < 3) { // Clan Skills for (k = 0; k < MAX_GUILDSKILL; k++) { gskill = k + GD_SKILLBASE; bg_guild[j].skill[k].id = gskill; switch (gskill) { case GD_GLORYGUILD: bg_guild[j].skill[k].lv = 0; break; case GD_APPROVAL: case GD_KAFRACONTRACT: case GD_GUARDRESEARCH: case GD_BATTLEORDER: case GD_RESTORE: case GD_EMERGENCYCALL: case GD_DEVELOPMENT: bg_guild[j].skill[k].lv = 1; break; case GD_GUARDUP: case GD_REGENERATION: bg_guild[j].skill[k].lv = 3; break; case GD_LEADERSHIP: case GD_GLORYWOUNDS: case GD_SOULCOLD: case GD_HAWKEYES: bg_guild[j].skill[k].lv = 5; break; case GD_EXTENSION: bg_guild[j].skill[k].lv = 10; break; } } } else { // Other Data snprintf(bg_guild[j].name, NAME_LENGTH, "Team %d", i - 3); // Team 1, Team 2 ... Team 10 strncpy(bg_guild[j].master, bg_guild[j].name, NAME_LENGTH); snprintf(bg_guild[j].position[0].name, NAME_LENGTH, "%s Leader", bg_guild[j].name); strncpy(bg_guild[j].position[1].name, bg_guild[j].name, NAME_LENGTH); } sprintf(gpath, "%s/%s/bg_%d.ebm", "plugins","hBG", i); if ((fp = fopen(gpath, "rb")) != NULL) { fseek(fp, 0, SEEK_END); bg_guild[j].emblem_len = (int)ftell(fp); fseek(fp, 0, SEEK_SET); fread(&bg_guild[j].emblem_data, 1, bg_guild[j].emblem_len, fp); fclose(fp); } else { ShowWarning("Error reading '"CL_WHITE"%s"CL_RESET"' emblem data file.\n", gpath); } } ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"' v%s emblem data files. [By Smokexyz]\n", pinfo.name, pinfo.version); // Guild Data - Guillaume strncpy(bg_guild[0].name, "Blue Team", NAME_LENGTH); strncpy(bg_guild[0].master, "General Guillaume", NAME_LENGTH); strncpy(bg_guild[0].position[0].name, "Blue Team Leader", NAME_LENGTH); strncpy(bg_guild[0].position[1].name, "Blue Team", NAME_LENGTH); // Guild Data - Croix strncpy(bg_guild[1].name, "Red Team", NAME_LENGTH); strncpy(bg_guild[1].master, "Prince Croix", NAME_LENGTH); strncpy(bg_guild[1].position[0].name, "Red Team Leader", NAME_LENGTH); strncpy(bg_guild[1].position[1].name, "Red Team", NAME_LENGTH); // Guild Data - Traitors strncpy(bg_guild[2].name, "Green Team", NAME_LENGTH); strncpy(bg_guild[2].master, "Mercenary", NAME_LENGTH); strncpy(bg_guild[2].position[0].name, "Green Team Leader", NAME_LENGTH); strncpy(bg_guild[2].position[1].name, "Green Team", NAME_LENGTH); } /** * Timer function for revealing/hiding mini map positions. * Also handles player AFK mechanic. * @see DBApply * @see hBG_send_xy_timer * @param data battleground data pointer. * @return int */ int hBG_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap) { struct battleground_data *bgd = DB->data2ptr(data); struct hBG_data *hBGd = getFromBGDATA(bgd, 0); char output[128]; int i, m, idle_announce = hBG_config_get("battle_configuration/hBG_idle_announce"), idle_autokick = hBG_config_get("battle_configuration/hBG_idle_autokick"); nullpo_ret(bgd); nullpo_ret(hBGd); m = map->mapindex2mapid(bgd->mapindex); hBGd->reveal_flag = !hBGd->reveal_flag; // Switch for (i = 0; i < MAX_BG_MEMBERS; i++) { struct map_session_data *sd = bgd->members[i].sd; struct hBG_map_session_data *hBGsd = NULL; if (sd == NULL || (hBGsd = getFromMSD(sd, 1)) == NULL) continue; if (idle_autokick && DIFF_TICK(sockt->last_tick, sd->idletime) >= idle_autokick && hBGd->g && map->list[sd->bl.m].flag.battleground) { sprintf(output, "[Battlegrounds] %s has been kicked for being AFK.", sd->status.name); clif->broadcast2(&sd->bl, output, (int)strlen(output)+1, hBGd->color, 0x190, 20, 0, 0, BG); bg->team_leave(sd,3); clif->message(sd->fd, "You have been kicked from the battleground because of your AFK status."); pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3); continue; } else if (sd->bl.x != bgd->members[i].x || sd->bl.y != bgd->members[i].y) { // xy update bgd->members[i].x = sd->bl.x; bgd->members[i].y = sd->bl.y; clif->bg_xy(sd); } if (hBGd->reveal_pos && hBGd->reveal_flag && sd->bl.m == m) map->foreachinmap(hBG_reveal_pos, m, BL_PC, sd, 1, hBGd->color); // Message for AFK Idling if (idle_announce && DIFF_TICK(sockt->last_tick, sd->idletime) >= idle_announce && !hBGsd->state.afk && hBGd->g) { // Set AFK status and announce to the team. hBGsd->state.afk = 1; sprintf(output, "%s : %s seems to be away. AFK Warning - Can be kicked out with @reportafk.", hBGd->g->name, sd->status.name); hBG_send_chat_message(bgd, sd->bl.id, sd->status.name, output, (int)strlen(output) + 1); } } return 0; } /** * Timer function for revealing/hiding mini map positions. * Also handles player AFK time. * @see hBG_send_xy_timer_sub */ int hBG_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { bg->team_db->foreach(bg->team_db, hBG_send_xy_timer_sub, tick); return 0; } /** * Add an item to the floor at m (x,y) * @param bl pointer to the block list. * @param m map index * @param x map x co-ordinate * @param y map y co-ordinate * @param nameid ID of the item to be dropped. * @param amount Amount of the item to be dropped. * @return count of the item dropped. */ int hBG_addflooritem_area(struct block_list* bl, int16 m, int16 x, int16 y, int nameid, int amount) { struct item item_tmp; int count, range, i; short mx, my; memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; if (bl != NULL) m = bl->m; count = 0; range = (int)sqrt((float)amount) +2; for ( i = 0; i < amount; i++) { if (bl != NULL) map->search_freecell(bl, 0, &mx, &my, range, range, 0); else { mx = x; my = y; map->search_freecell(NULL, m, &mx, &my, range, range, 1); } count += (map->addflooritem(bl, &item_tmp, 1, m, mx, my, 0, 0, 0, 4, false) != 0) ? 1 : 0; } return count; } // @TODO void hBG_bg_ranking_display(struct map_session_data *sd, bool ranked) { struct hBG_map_session_data *hBGsd = NULL; nullpo_retv(sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; // print shit. } void hBG_record_mobkills(struct map_session_data *sd, struct mob_data *md) { struct battleground_data *bgd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; nullpo_retv(sd); nullpo_retv(md); if (map->list[sd->bl.m].flag.battleground && sd->bg_id) { int i; if ((bgd = bg->team_search(sd->bg_id)) == NULL) return; if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == sd); if (i >= MAX_BG_MEMBERS) return; switch ( md->class_) { case E_BAPHOMET2: case E_LORD_OF_DEATH2: case E_DARK_LORD: case E_KTULLANUX: case E_DARK_SNAKE_LORD: add2limit(hBGsd->stats.boss_killed, 1, USHRT_MAX); break; case E_TURTLE_GENERAL: case E_APOCALIPS_H: add2limit(hBGsd->stats.guardian_stone_kills, 1, USHRT_MAX); break; case E_FALLINGBISHOP: if (map->list[sd->bl.m].flag.battleground == 2) add2limit(hBGsd->stats.ru_captures, 1, USHRT_MAX); break; case OBJ_NEUTRAL: if (strcmpi(map->list[sd->bl.m].name, "bat_a03") == 0) add2limit(hBGsd->stats.boss_flags, 1, USHRT_MAX); break; case BARRICADE_: if (strcmpi(map->list[sd->bl.m].name, "bat_a01") == 0) add2limit(hBGsd->stats.barricade_kills, 1, USHRT_MAX); break; } } } void hBG_record_damage(struct block_list *src, struct block_list *target, int damage) { struct block_list *s_bl = NULL; struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; if (src == NULL || target == NULL || src == target || damage <= 0) return; if ((s_bl = battle->get_master(src)) == NULL) s_bl = src; if (s_bl->type != BL_PC) return; if ((sd = BL_UCAST(BL_PC, s_bl)) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return; switch ( target->type) { case BL_PC: { struct map_session_data *tsd = NULL; struct hBG_map_session_data *hBGtsd = NULL; if ((tsd = BL_UCAST(BL_PC, target)) == NULL) break; if ((hBGtsd = getFromMSD(tsd, 1)) == NULL) break; if (map->list[src->m].flag.battleground && sd->bg_id) { add2limit(hBGsd->stats.total_damage_done, damage, UINT_MAX); add2limit(hBGtsd->stats.total_damage_received, damage, UINT_MAX); if (hBGsd->stats.best_damage < damage) hBGsd->stats.best_damage = damage; } } break; case BL_MOB: { struct mob_data *md = BL_UCAST(BL_MOB, target); if (map->list[src->m].flag.battleground && sd->bg_id && md->class_ >= E_BAPHOMET2 && md->class_ <= E_FALLINGBISHOP) add2limit(hBGsd->stats.boss_damage, damage, USHRT_MAX); } break; } } /** * Warps a Team * @see hBG_warp */ int hBG_team_warp(int bg_id, unsigned short mapidx, short x, short y) { // Warps a Team int i; struct battleground_data *bgd = bg->team_search(bg_id); if (bgd == NULL) { ShowError("buildin_hBG_team_warp: Invalid teamId %d provided!", bg_id); return false; } if (mapidx == 0) { // BG Cemetery (Spawn Point) mapidx = bgd->mapindex; x = bgd->x; y = bgd->y; } for (i = 0; i < bgd->count; i++) if (bgd->members[i].sd != NULL) pc->setpos(bgd->members[i].sd, mapidx, x, y, CLR_TELEPORT); return true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @Commands * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Display battleground rankings. */ ACMD(bgrank) { char mode[7]; char atcmd_output[256]; memset(atcmd_output, '\0', sizeof(atcmd_output)); if (!*message || sscanf(message, "%7s", mode) < 1) { sprintf(atcmd_output, "Please, enter a battleground mode (usage: @bgrank <ranked/normal>)."); clif->message(fd, atcmd_output); return false; } if (strncmpi(mode, "ranked", 7) == 0) { hBG_bg_ranking_display(sd, true); } else if (strncmpi(mode, "normal", 7) == 0) { hBG_bg_ranking_display(sd, true); } else { sprintf(atcmd_output, "Please, enter a battleground mode (usage: @bgrank <ranked/normal>)."); clif->message(fd, atcmd_output); return false; } return true; } ACMD(reportafk) { struct map_session_data *pl_sd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_map_session_data *hBGpl_sd = NULL; struct battleground_data *bgd = NULL; if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) clif->message(fd, "This command is reserved for Battlegrounds Only."); else if (!(hBGd->leader_char_id == sd->status.char_id) && hBG_config_get("battle_configuration/hBG_reportafk_leaderonly")) clif->message(fd, "This command is reserved for Team Leaders Only."); else if (!*message) clif->message(fd, "Please, enter the character name (usage: @reportafk <name>)."); else if ((pl_sd = map->nick2sd(message)) == NULL) clif->message(fd, msg_txt(3)); // Character not found. else if ((hBGpl_sd = getFromMSD(pl_sd, 0)) == NULL) clif->message(fd, "Destination Player is not in battlegrounds."); else if (sd->bg_id != pl_sd->bg_id) clif->message(fd, "Destination Player is not in your Team."); else if (sd == pl_sd) clif->message(fd, "You cannot kick yourself."); else if (!hBGpl_sd->state.afk) clif->message(fd, "The player is not AFK on this Battleground."); else { // Everything is fine! char atcmd_output[256]; // Kick the player and send a message. bg->team_leave(pl_sd, 2); clif->message(pl_sd->fd, "You have been kicked from Battleground because of your AFK status."); pc->setpos(pl_sd, pl_sd->status.save_point.map, pl_sd->status.save_point.x, pl_sd->status.save_point.y, 3); // Message the source player and announce to team. sprintf(atcmd_output, "%s has been successfully kicked.", pl_sd->status.name); clif->broadcast2(&sd->bl, atcmd_output, (int)strlen(atcmd_output)+1, hBGd->color, 0x190, 20, 0, 0, BG); return true; } return false; } /** * Change Team Leader. */ ACMD(leader) { struct map_session_data *pl_sd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_map_session_data *hBGpl_sd = NULL; struct battleground_data *bgd = NULL; if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) clif->message(fd, "This command is reserved for Battlegrounds Only."); else if (sd->ud.skilltimer != INVALID_TIMER) clif->message(fd, "Command not allow while casting a skill."); else if (!(hBG_config_get("battle_configuration/hBG_leader_change"))) clif->message(fd, "This command is disabled."); else if (!(hBGd->leader_char_id == sd->status.char_id)) clif->message(fd, "This command is reserved for Team Leaders Only."); else if (!*message) clif->message(fd, "Please, enter the character name (usage: @leader <name>)."); else if ((pl_sd = map->nick2sd(message)) == NULL) clif->message(fd, msg_txt(3)); // Character not found. else if ((hBGpl_sd = getFromMSD(pl_sd, 0)) == NULL) clif->message(fd, "Destination Player is not in battlegrounds."); else if (sd->bg_id != pl_sd->bg_id) clif->message(fd, "Destination Player is not in your Team."); else if (sd == pl_sd) clif->message(fd, "You are already the Team Leader."); else { // Everything is fine... more or less. char atcmd_output[256]; sprintf(atcmd_output, "Team Leader transfered to [%s]", pl_sd->status.name); clif->broadcast2(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, hBGd->color, 0x190, 20, 0, 0, BG); hBGd->leader_char_id = pl_sd->status.char_id; clif->charnameupdate(sd); clif->charnameupdate(pl_sd); return true; } return false; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Script Commands * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Send out a battleground announcement. * @param mes * @param fontColor * @param fontType * @param fontSize * @param fontAlign * @param fontY */ BUILDIN(hBG_announce) { const char *mes = script_getstr(st,2); const char *fontColor = script_hasdata(st,3) ? script_getstr(st,3) : NULL; int fontType = script_hasdata(st,4) ? script_getnum(st,4) : 0x190; // default fontType (FW_NORMAL) int fontSize = script_hasdata(st,5) ? script_getnum(st,5) : 12; // default fontSize int fontAlign = script_hasdata(st,6) ? script_getnum(st,6) : 0; // default fontAlign int fontY = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontY clif->broadcast2(NULL, mes, (int)strlen(mes) + 1, (unsigned int)strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, ALL_CLIENT); return true; } /** * Count the number of logins per IP in battleground * @return count of accounts on same ip. */ BUILDIN(hBG_logincount) { struct map_session_data *sd = script->rid2sd(st); int i = 0; if (sd) i = hBG_countlogin(sd,true); script_pushint(st,i); return true; } /** * Create a BG Team. * @param map_name Respawn Map Name * @param map_x Respawn Map X * @param map_y Respawn Map Y * @param guild_index BG Guild Index * @param ev Logout Event * @param dev Die Event */ BUILDIN(hBG_team_create) { const char *map_name, *ev = "", *dev = ""; int x, y, m = 0, guild_index, bg_id; map_name = script_getstr(st, 2); if (strcmp(map_name,"-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 3); y = script_getnum(st, 4); guild_index = script_getnum(st, 5); ev = script_getstr(st, 6); // Logout Event dev = script_getstr(st, 7); // Die Event guild_index = cap_value(guild_index, 0, 12); bg_id = hBG_create(m, x, y, guild_index, ev, dev); script_pushint(st, bg_id); return true; } /** * Create a Queue * @param queue_name Name of the Queue * @param jev Join Event * @param min_level Minimum level to join the queue. * @return queue Id */ BUILDIN(hBG_queue_create) { const char *queue_name, *jev; int min_level = 0; queue_name = script_getstr(st, 2); jev = script_getstr(st, 3); if (script_hasdata(st, 4)) min_level = script_getnum(st, 4); script_pushint(st, hBG_queue_create(queue_name, jev, min_level)); return true; } /** * Changes/Sets the Queue's Join Event. * @param queue_id * @param jev On Join Event */ BUILDIN(hBG_queue_event) { struct hBG_queue_data *hBGqd; const char *join_event; int q_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st, 0); return false; } join_event = script_getstr(st,3); safestrncpy(hBGqd->join_event, join_event, sizeof(hBGqd->join_event)); script_pushint(st, 1); return true; } /** * Makes a player join a queue. * @param Queue ID */ BUILDIN(hBG_queue_join) { int q_id; struct map_session_data *sd = script->rid2sd(st); nullpo_retr(false, sd); q_id = script_getnum(st,2); script_pushint(st, hBG_queue_join(sd, q_id)); return true; } /** * Makes party join a queue. * @param Party ID * @param Queue ID */ BUILDIN(hBG_queue_partyjoin) { int q_id, i, party_id; struct map_session_data *sd; struct party_data *p; party_id = script_getnum(st,2); if (party_id <= 0 || (p = party->search(party_id)) == NULL) { script_pushint(st, 0); return false; } q_id = script_getnum(st,3); if (hBG_queue_search(q_id) == NULL) { script_pushint(st, 0); return false; } for (i = 0; i < MAX_PARTY; i++) { if ((sd = p->data[i].sd) == NULL) continue; hBG_queue_join(sd,q_id); } script_pushint(st, 1); return true; } /** * Makes a player leave a queue. * @param Queue ID */ BUILDIN(hBG_queue_leave) { int q_id; struct map_session_data *sd = script->rid2sd(st); nullpo_retr(false, sd); q_id = script_getnum(st,2); script_pushint(st, hBG_queue_leave(sd, q_id)); return true; } /** * Request queue information * @param Queue ID * @param Information Type * 0) Users * 1) Copy user list to $@qmembers$ variable and return count. */ BUILDIN(hBG_queue_data) { struct hBG_queue_data *hBGqd; int q_id = script_getnum(st,2), type = script_getnum(st,3); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st,0); return false; } switch (type) { case 0: script_pushint(st, hBGqd->users); return true; case 1: // User List { int j = 0; struct map_session_data *sd; struct hBG_queue_member *head; head = hBGqd->first; while (head) { if ((sd = head->sd) != NULL) { mapreg->setregstr(reference_uid(script->add_str("$@qmembers$"),j),sd->status.name); j++; } head = head->next; } script_pushint(st,j); } return true; default: ShowError("script:hBG_queue_data: unknown queue data type %d.\n", type); break; } script_pushint(st, 0); return true; } /** * Adds all members in queue to a BG team. * @param Queue ID * @param Max Team Members * @param Respawn Map Name * @param Respawn Map X * @param Respawn Map Y * @param BG Guild Index * @param Logout Event * @param Die Event * @return Battleground Id */ BUILDIN(hBG_queue2team) { struct hBG_queue_data *hBGqd; struct hBG_queue_member *qm; const char *map_name, *ev = "", *dev = ""; int q_id, max, x, y, i, m=0, guild_index, bg_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL) { script_pushint(st, 0); return false; } max = script_getnum(st,3); map_name = script_getstr(st,4); if (strcmp(map_name,"-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st,5); y = script_getnum(st,6); guild_index = script_getnum(st,7); ev = script_getstr(st,8); // Logout Event dev = script_getstr(st,9); // Die Event guild_index = cap_value(guild_index, 0, 12); if ((bg_id = hBG_create(m, x, y, guild_index, ev, dev)) == 0) { script_pushint(st, 0); return false; } i = 0; // Counter while ((qm = hBGqd->first) != NULL && i < max && i < MAX_BG_MEMBERS) { if (qm->sd && hBG_team_join(bg_id, qm->sd)) { mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), qm->sd->bl.id); hBG_queue_member_remove(hBGqd, qm->sd->bl.id); i++; } else { break; // Failed? Should not. Anyway, to avoid a infinite loop } } mapreg->setreg(script->add_str("$@arenamembersnum"), i); script_pushint(st, bg_id); return true; } /** * Joins the first player in the queue to the given team and warps him. * @param Queue ID * @param Battleground ID * @param Spawn Map Name * @param Spawn Map X Co-ordinate * @param Spawn Map Y Co-ordinate */ BUILDIN(hBG_queue2team_single) { const char* map_name; struct hBG_queue_data *hBGqd; struct map_session_data *sd; int x, y, m, bg_id, q_id; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL || !hBGqd->first || !hBGqd->first->sd) { script_pushint(st, 0); return false; } bg_id = script_getnum(st, 3); map_name = script_getstr(st, 4); if ((m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 5); y = script_getnum(st, 6); sd = hBGqd->first->sd; if (hBG_team_join(bg_id, sd)) { hBG_queue_member_remove(hBGqd, sd->bl.id); pc->setpos(sd, m, x, y, CLR_TELEPORT); script_pushint(st, 1); } return true; } /** * Check if the given BG Queue can start a BG in the given mode. * @param Queue ID * @param Type * @param Teams * @param Required Minimum Players * @return 1 can start, 0 cannot start. */ BUILDIN(hBG_queue_checkstart) { int q_id, result = 0; struct hBG_queue_data *hBGqd; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) != NULL) { int type, req_min, teams; type = script_getnum(st,3); teams = script_getnum(st,4); req_min = script_getnum(st,5); switch (type) { case 0: // Lineal, as they Join case 1: // Random if (hBGqd->users >= (req_min * teams)) result = 1; break; default: result = 0; break; } } script_pushint(st, result); return true; } /** * Build BG Teams from one Queue * @param Queue ID * @param Minimum Players * @param Maximum Players per Team * @param Type * @param ... Team ID */ BUILDIN(hBG_queue2teams) { // Send Users from Queue to Teams. Requires previously created teams. struct hBG_queue_data *hBGqd; int t, bg_id = 0, total_teams = 0, q_id, min, max, type, limit = 0; int arg_offset = 6; struct map_session_data *sd; q_id = script_getnum(st,2); // Queue ID if ((hBGqd = hBG_queue_search(q_id)) == NULL) { ShowError("buildin_hBG_queue2teams: Non existant queue id received %d.\n", q_id); script_pushint(st, 0); return false; } min = script_getnum(st,3); // Min Members per Team max = script_getnum(st,4); // Max Members per Team type = script_getnum(st,5); // Team Building Method t = arg_offset; // Team ID's to build while (script_hasdata(st,t) && t < MAX_BATTLEGROUND_TEAMS+arg_offset) { bg_id = script_getnum(st,t); if (bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_queue2teams: Non existant team Id received %d.\n", bg_id); script_pushint(st, 0); return false; } t++; } total_teams = t - arg_offset; if (total_teams < 2) { ShowError("buildin_hBG_queue2teams: Less than 2 teams received to build members.\n"); script_pushint(st, 0); return false; } if (hBGqd->users < min) { ShowError("buildin_hBG_queue2teams: Less than minimum %d queue members received (%d).\n", min, (int) hBGqd->users); script_pushint(st, 0); return false; } // How many players are we going to take from the Queue limit = min(max * total_teams, hBGqd->users); switch (type) { case 0: // Lineal - Maybe to keep party together { t = 0; int i = 0; for (i = 0; i < limit; i++) { if ((i%(limit/total_teams)) == 0) // Switch Team bg_id = script_getnum(st,t+arg_offset); if (!hBGqd->first || (sd = hBGqd->first->sd) == NULL) break; // No more people to join Teams hBG_team_join(bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); // Increment Team counter or break if (t++ >= total_teams) break; } } break; default: case 1: // Random { t = 0; int pos = 0, i=0; struct hBG_queue_member *qm; for (i=0; t < limit; i++) { if ((i%(limit/total_teams)) == 0) // Switch Team bg_id = script_getnum(st,t+arg_offset); pos = 1 + rand() % (limit - i); if ((qm = hBG_queue_member_get(hBGqd, pos)) == NULL || (sd = qm->sd) == NULL) break; hBG_team_join(bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); // Increment Team Counter or break if (t++ >= total_teams) break; } } break; } script_pushint(st, 1); return true; } /** * Fill teams with members from the given Queue. * @param Queue ID * @param Max Players Per Team * @param Balanceing method * @param Team 1 ... Team 13 */ BUILDIN(hBG_balance_teams) { struct hBG_queue_data *hBGqd; struct hBG_queue_member *head; struct battleground_data *bgd, *p_bg; int i, c, q_id, bg_id, m_bg_id = 0, max, min, type; struct map_session_data *sd; bool balanced; q_id = script_getnum(st,2); if ((hBGqd = hBG_queue_search(q_id)) == NULL || hBGqd->users <= 0) { ShowError("buildin_hBG_balance_teams: Non existant Queue Id or the queue is empty.\n"); script_pushint(st, 0); return false; } max = script_getnum(st,3); if (max > MAX_BG_MEMBERS) max = MAX_BG_MEMBERS; min = MAX_BG_MEMBERS + 1; type = script_getnum(st, 4); i = 5; // Team IDs to build while (script_hasdata(st, i) && i-5 < 13) { bg_id = script_getnum(st, i); if ((bgd = bg->team_search(bg_id)) == NULL) { ShowError("buildin_hBG_balance_teams: Non existant team id received %d.\n", bg_id); script_pushint(st, 0); return false; } if (bgd->count < min) min = bgd->count; i++; } c = i - 5; // Teams Found if (c < 2 || min >= max) return true; // No Balance Required if (type < 3) { while ((head = hBGqd->first) != NULL && (sd = head->sd) != NULL) { p_bg = NULL; balanced = true; min = MAX_BG_MEMBERS + 1; // Search the Current Minimum and Balance status for (i = 0; i < c; i++) { bg_id = script_getnum(st,i+5); if ((bgd = bg->team_search(bg_id)) == NULL) break; // Should not happen. Teams already check if (p_bg && p_bg->count != bgd->count) balanced = false; // Teams still with different member count if (bgd->count < min) { m_bg_id = bg_id; min = bgd->count; } p_bg = bgd; } if (min >= max) break; // Balance completed if (hBG_config_get("battle_configuration/hBG_balanced_queue") && balanced && hBGqd->users < c) break; // No required users on queue to keep balance hBG_team_join(m_bg_id, sd); hBG_queue_member_remove(hBGqd, sd->bl.id); if ((bgd = bg->team_search(m_bg_id)) != NULL && bgd->mapindex) pc->setpos(sd, bgd->mapindex, bgd->x, bgd->y, CLR_TELEPORT); // Joins and Warps } } else { ShowError("buildin_hBG_balance_teams: Invalid type %d given for argument #3.\n", type); script_pushint(st, 0); return false; } script_pushint(st, 1); return true; } /** * Waiting Room to Battleground Teams * @param Map Name * @param Map X * @param Map Y * @param BG Guild Index * @param Logout Event * @param Die Event */ BUILDIN(hBG_waitingroom2bg) { struct npc_data *nd; struct chat_data *cd; const char *map_name, *ev = "", *dev = ""; int x, y, i, m=0, guild_index, bg_id; struct map_session_data *sd; nd = (struct npc_data *)map->id2bl(st->oid); if (nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL) { script_pushint(st, 0); return false; } map_name = script_getstr(st,2); if (strcmp(map_name, "-") != 0 && (m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; } x = script_getnum(st, 3); y = script_getnum(st, 4); guild_index = script_getnum(st, 5); ev = script_getstr(st, 6); // Logout Event dev = script_getstr(st, 7); // Die Event guild_index = cap_value(guild_index, 0, 12); if ((bg_id = hBG_create(m, x, y, guild_index, ev, dev)) == 0) { // Creation failed script_pushint(st, 0); return false; } for (i = 0; i < cd->users && i < MAX_BG_MEMBERS; i++) { if ((sd = cd->usersd[i]) != NULL && hBG_team_join(bg_id, sd)) mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), sd->bl.id); else mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), 0); } mapreg->setreg(script->add_str("$@arenamembersnum"), i); script_pushint(st, bg_id); return true; } /** * Adds the first player from the given NPC's * waiting room to BG Team. * @param Battleground Id * @param Map Name * @param Map X * @param Map Y * @param NPC Name */ BUILDIN(hBG_waitingroom2bg_single) { const char* map_name; struct npc_data *nd; struct chat_data *cd; struct map_session_data *sd; int x, y, m, bg_id; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if ((m = mapindex->name2id(map_name)) == 0) { script_pushint(st, 0); return false; // Invalid Map } x = script_getnum(st,4); y = script_getnum(st,5); nd = npc->name2id(script_getstr(st,6)); if (nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL || cd->users <= 0) { script_pushint(st, 0); return false; } if ((sd = cd->usersd[0]) == NULL) { script_pushint(st, 0); return false; } if (hBG_team_join(bg_id, sd)) { pc->setpos(sd, m, x, y, CLR_TELEPORT); script_pushint(st,1); } else { script_pushint(st,0); } return true; } /** * Set the Respawn Location of a BG team * @param Battleground Id * @param Map X * @param Map Y */ BUILDIN(hBG_team_setxy) { struct battleground_data *bgd; int bg_id; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL) { script_pushint(st, 0); return false; } bgd->x = script_getnum(st,3); bgd->y = script_getnum(st,4); script_pushint(st, 1); return true; } /** * Reveal the location of a BG Team on the minimap. * @param Battleground ID */ BUILDIN(hBG_team_reveal) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } hBGd->reveal_pos = true; // Reveal Position Mode script_pushint(st, 1); return true; } /** * Conceal the location of a BG Team from the minimap. * @param Battleground ID */ BUILDIN(hBG_team_conceal) { struct battleground_data *bgd; struct hBG_data *hBGd; struct map_session_data *sd; int bg_id,i=0; bg_id = script_getnum(st,2); if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; hBG_send_dot_remove(sd); } hBGd->reveal_pos = false; // Conceal Position Mode script_pushint(st, 1); return true; } /** * Set Quest for a BG Team * @param Battleground ID * @param Quest ID */ BUILDIN(hBG_team_setquest) { struct battleground_data *bgd; struct map_session_data *sd; int i, bg_id, qid; bg_id = script_getnum(st,2); qid = script_getnum(st,3); if (bg_id <= 0 || (bgd = bg->team_search(bg_id)) == NULL) { ShowError("buildin_hBG_team_setquest: Invalid Team ID %d given.\n", bg_id); script_pushint(st, 0); return false; } if (qid <= 0 || quest->db(qid) == NULL) { ShowError("buildin_hBG_team_setquest: Invalid Quest ID %d given.\n", qid); script_pushint(st, 0); return false; } for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; quest->add(sd, qid, 0); } script_pushint(st, 1); return true; } /** * Set Viewpoint for a player. * @see hBG_viewpointmap */ int hBG_viewpointmap_sub(struct block_list *bl, va_list ap) { struct map_session_data *sd; int npc_id, type, x, y, id, color; npc_id = va_arg(ap,int); type = va_arg(ap,int); x = va_arg(ap,int); y = va_arg(ap,int); id = va_arg(ap,int); color = va_arg(ap,int); sd = (struct map_session_data *)bl; clif->viewpoint(sd,npc_id,type,x,y,id,color); return 0; } /** * Set Viewpoint on minimap for a player. * @param Map Name * @param Type * 0 = display mark for 15 seconds * 1 = display mark until dead or teleported * 2 = remove mark * @param Map X * @param Map Y * @param ID (Unique ID of the viewpoint) * @param Color */ BUILDIN(hBG_viewpointmap) { int type,x,y,id,color,m; const char *map_name; map_name = script_getstr(st,2); if ((m = map->mapname2mapid(map_name)) < 0) { script_pushint(st, 0); return false; // Invalid Map } type=script_getnum(st,3); x=script_getnum(st,4); y=script_getnum(st,5); id=script_getnum(st,6); color=script_getnum(st,7); map->foreachinmap(hBG_viewpointmap_sub,m,BL_PC,st->oid,type,x,y,id,color); script_pushint(st, 1); return true; } /** * Reveal a monster's location on minimap * @param Monster Id * @param Type * 0 = display mark for 15 seconds * 1 = display mark until dead or teleported * 2 = remove mark * @param Color */ BUILDIN(hBG_monster_reveal) { struct block_list *mbl; int id = script_getnum(st,2), flag = script_getnum(st,3), color = script_getnum(st,4); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } map->foreachinmap(hBG_viewpointmap_sub, mbl->m, BL_PC, st->oid, flag, mbl->x, mbl->y, mbl->id, color); script_pushint(st, 1); return true; } /** * Set monster as an ally to a BG Team. * @param Monster ID * @param Battleground ID */ BUILDIN(hBG_monster_set_team) { struct mob_data *md; struct block_list *mbl; int id = script_getnum(st,2), bg_id = script_getnum(st,3); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } md = (TBL_MOB *)mbl; md->bg_id = bg_id; mob_stop_attack(md); mob_stop_walking(md, 0); md->target_id = md->attacked_id = 0; clif->charnameack(0, &md->bl); script_pushint(st, 1); return true; } /** * Set immunity flag to a monster. * (making it immune to damage). * @param Monster ID * @param Flag (0 = Off | 1 = On) */ BUILDIN(hBG_monster_immunity) { struct mob_data *md; struct block_list *mbl; struct hBG_mob_data *hBGmd; int id = script_getnum(st,2), flag = script_getnum(st,3); if (id == 0 || (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB) { script_pushint(st, 0); return false; } md = (TBL_MOB *)mbl; if ((hBGmd = getFromMOBDATA(md, 0)) == NULL){ CREATE(hBGmd, struct hBG_mob_data, 1); addToMOBDATA(md, hBGmd, 0, true); } hBGmd->state.immunity = flag; return true; } /** * Leave a Battleground Team */ BUILDIN(hBG_leave) { struct map_session_data *sd = script->rid2sd(st); if (sd == NULL || sd->bg_id == 0) { script_pushint(st, 0); return false; } bg->team_leave(sd,0); script_pushint(st, 1); return true; } /** * Finalize battlegrounds and remove * teams from the db. */ BUILDIN(hBG_destroy) { int bg_id = script_getnum(st, 2); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_destroy: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } hBG_team_finalize(bg_id, true); script_pushint(st, 1); return true; } /** * Clean Battlegrounds without removing * the teams from the db. */ BUILDIN(hBG_clean) { int bg_id = script_getnum(st, 2); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_clean: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } hBG_team_finalize(bg_id, false); script_pushint(st, 1); return true; } /** * Get user count within an area in a map. * @param Battleground ID * @param Map Name * @param X1 * @param Y1 * @param X2 * @param Y2 */ BUILDIN(hBG_getareausers) { struct battleground_data *bgd = NULL; struct map_session_data *sd = NULL; const char *map_name; int m, x0, y0, x1, y1, bg_id; int i = 0, c = 0; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if ((bgd = bg->team_search(bg_id)) == NULL || (m = map->mapname2mapid(map_name)) < 0) { script_pushint(st,0); return false; } x0 = script_getnum(st,4); y0 = script_getnum(st,5); x1 = script_getnum(st,6); y1 = script_getnum(st,7); for (i = 0; i < MAX_BG_MEMBERS; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; else if (sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) continue; c++; } script_pushint(st, c); return true; } /** * Update the score on a battleground map. * @param Map Name * @param Lion Score * @param Eagle Score */ BUILDIN(hBG_updatescore) { const char *map_name; int m; map_name = script_getstr(st,2); if ((m = map->mapname2mapid(map_name)) < 0) { script_pushint(st, 0); return false; } map->list[m].bgscore_lion = script_getnum(st,3); map->list[m].bgscore_eagle = script_getnum(st,4); clif->bg_updatescore(m); script_pushint(st, 1); return true; } /** * Update Score for a Battleground Team. * @param Battleground ID * @param Score */ BUILDIN(hBG_update_score_team) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2); int score = script_getnum(st,3); if (bg_id <= 0) { ShowError("buildin_hBG_update_score_team: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } hBGd->team_score = score; hBG_update_score_team(bgd); script_pushint(st, 1); return true; } /** * Get a Team's Guild Index * @param Battleground ID * @return Guild Index */ BUILDIN(hBG_get_team_gid) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2), guild_id = 0; if (bg_id <= 0) { ShowError("buildin_hBG_get_team_gid: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL) guild_id = hBGd->g->guild_id; script_pushint(st, guild_id); return true; } /** * Get data from a Battleground * @param Battleground ID * @param Type * 0 = User Count * 1 = Fill $@bgmembers$ array with user list and return user count. * 2 = BG Guild Name * 3 = BG Guild Master Name * 4 = BG Color */ BUILDIN(hBG_get_data) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id = script_getnum(st,2); int type = script_getnum(st,3); if (bg_id <= 0) { ShowError("buildin_hBG_get_data: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if ((bgd = bg->team_search(bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) { script_pushint(st, 0); return false; } switch (type) { case 0: script_pushint(st, bgd->count); break; case 1: // Users and List { int i, j = 0; struct map_session_data *sd; for (i = 0; i < bgd->count; i++) { if ((sd = bgd->members[i].sd) == NULL) continue; mapreg->setregstr(reference_uid(script->add_str("$@bgmembers$"),j),sd->status.name); j++; } script_pushint(st, j); } break; case 2: script_pushconststr(st,hBGd->g ? hBGd->g->name : ""); break; case 3: script_pushconststr(st,hBGd->g ? hBGd->g->master : ""); break; case 4: script_pushint(st,hBGd->color); break; default: ShowError("script:bg_get_data: unknown data identifier %d\n", type); break; } script_pushint(st, 0); return true; } /** * Battleground Get Item * @param Battleground ID * @param Item ID * @param Item Amount */ BUILDIN(hBG_getitem) { int bg_id, nameid, amount; bg_id = script_getnum(st,2); nameid = script_getnum(st,3); amount = script_getnum(st,4); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_getitem: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } else if (nameid <= 0 || itemdb->exists(nameid) == NULL) { ShowError("buildin_hBG_getitem: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } else if (amount <= 0) { ShowError("buildin_hBG_getitem: Invalid Item amount %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_team_getitem(bg_id, nameid, amount); script_pushint(st, amount); return true; } /** * Battleground Get Kafra Points * @param Battleground ID * @param Amount of KP */ BUILDIN(hBG_getkafrapoints) { int bg_id, amount; bg_id = script_getnum(st, 2); amount = script_getnum(st, 3); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_getkafrapoints: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } else if (amount <= 0) { ShowError("buildin_hBG_getkafrapoints: Invalid Kafra Points %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_team_get_kafrapoints(bg_id, amount); script_pushint(st, amount); return true; } /** * Battleground get Rewards * @param Battleground ID * @param Item ID * @param Item Amount * @param Kafra Points * @param Quest ID * @param Custom Variable (#KAFRAPOINTS/#CASHPOINTS etc..) * @param Custom Variable Add Value * @param Battleground Arena (0 EoS | 1 Boss | 2 TI | 3 CTF | 4 TD | 5 SC | 6 CON | 7 RUSH | 8 DOM) * @param Battleground Result (0 Won | 1 Tie | 2 Lost) */ BUILDIN(hBG_reward) { int bg_id, nameid, amount, kafrapoints, quest_id, add_value, bg_arena, bg_result; const char *var; bg_id = script_getnum(st,2); nameid = script_getnum(st,3); amount = script_getnum(st,4); kafrapoints = script_getnum(st,5); quest_id = script_getnum(st,6); var = script_getstr(st,7); add_value = script_getnum(st,8); bg_arena = script_getnum(st,9); bg_result = script_getnum(st,10); if (bg_id <= 0 || bg->team_search(bg_id) == NULL) { ShowError("buildin_hBG_reward: Invalid BG Id %d provided.\n", bg_id); script_pushint(st, 0); return false; } if (nameid <= 0 || itemdb->exists(nameid) == NULL) { ShowError("buildin_hBG_reward: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } if (nameid > 0 && amount <= 0) { ShowError("buildin_hBG_reward: Invalid Item amount %d provided.\n", nameid); script_pushint(st, 0); return false; } if (kafrapoints < 0) { ShowError("buildin_hBG_reward: Invalid Kafra Points %d provided.\n", kafrapoints); script_pushint(st, 0); return false; } if (quest_id < 0 || quest->db(quest_id) == NULL) { ShowError("buildin_hBG_reward: Invalid Quest ID %d provided.\n", quest_id); script_pushint(st, 0); return false; } if (bg_arena < 0) { ShowError("buildin_hBG_reward: Invalid BG Arena %d provided. \n", bg_arena); script_pushint(st, 0); return false; } if (bg_result < 0 || bg_result > 2) { ShowError("buildin_hBG_reward: Invalid BG result type %d provided. (types - 0 Won | 1 Tie | 2 Lost)", bg_result); script_pushint(st, 0); return false; } hBG_team_rewards(bg_id, nameid, amount, kafrapoints, quest_id, var, add_value, bg_arena, bg_result); script_pushint(st, 1); return true; } /** * Add Item to XY co-ordinates on Floor. * @param Map Name * @param Map X * @param Map Y * @param Item ID * @param Item Amount */ BUILDIN(hBG_flooritem2xy) { int nameid, amount, m, x, y; const char *mapname; mapname = script_getstr(st,2); if ((m = map->mapname2mapid(mapname)) < 0) { // error message is thrown through mapindex->name2id() script_pushint(st, 0); return false; } x = script_getnum(st,3); y = script_getnum(st,4); nameid = script_getnum(st,5); if (itemdb->search(nameid) == NULL) { ShowError("buildin_hBG_flooritem2xy: Invalid Item Id %d provided.\n", nameid); script_pushint(st, 0); return false; } amount = script_getnum(st,6); if (amount < 1) { ShowError("buildin_hBG_flooritem2xy: Invalid Item amount %d provided.\n", amount); script_pushint(st, 0); return false; } hBG_addflooritem_area(NULL, m, x, y, nameid, amount); script_pushint(st, amount); return true; } /** * Warps BG Team to destination or Respawn Point * @param BG Team * @param Map Name * @param Map X * @param Map Y */ BUILDIN(hBG_warp) { int x, y, mapidx, bg_id; const char *map_name; bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if (!strcmp(map_name,"RespawnPoint")) // Cemetery Zone mapidx = 0; else if ((mapidx = script->mapindexname2id(st,map_name)) == 0) return 0; // Invalid Map x = script_getnum(st,4); y = script_getnum(st,5); bg_id = hBG_team_warp(bg_id, mapidx, x, y); return true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Map Server Function Pre-Hooks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * NPC Pre-Hooks */ void npc_parse_unknown_mapflag_pre(const char **name, const char **w3, const char **w4, const char **start, const char **buffer, const char **filepath, int **retval) { int16 m = map->mapname2mapid(*name); if (strcmpi(*w3, "hBG_topscore") == 0) { struct hBG_mapflag *hBG_mf; if ((hBG_mf = getFromMAPD(&map->list[m], 0)) == NULL) { CREATE(hBG_mf, struct hBG_mapflag, 1); hBG_mf->hBG_topscore = 1; addToMAPD(&map->list[m], hBG_mf, 0, true); } hBG_mf->hBG_topscore = 1; hookStop(); } return; } /** * Clif Pre-Hooks */ void clif_charnameupdate_pre(struct map_session_data **sd) { unsigned char buf[103]; int cmd = 0x195, ps; struct battleground_data *bgd = bg->team_search((*sd)->bg_id); struct hBG_data *hBGd; nullpo_retv((*sd)); if ((*sd)->fakename[0] || bgd == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL || hBGd->g == NULL) return; //No need to update as the guild was not displayed anyway. WBUFW(buf,0) = cmd; WBUFL(buf,2) = (*sd)->bl.id; memcpy(WBUFP(buf,6), (*sd)->status.name, NAME_LENGTH); WBUFB(buf,30) = 0; memcpy(WBUFP(buf,54), hBGd->g->name, NAME_LENGTH); ps = (hBGd->leader_char_id == (*sd)->status.char_id)?0:1; memcpy(WBUFP(buf,78), hBGd->g->position[ps].name, NAME_LENGTH); // Update nearby clients clif->send(buf, 102, &(*sd)->bl, AREA); hookStop(); } //Prevent update Guild Info if you're in BG void clif_parse_GuildRequestInfo_pre(int *fd, struct map_session_data **sd) { if ((*sd) && (*sd)->bg_id) hookStop(); return; } /** * Skill Pre-Hooks. */ int skill_check_condition_castbegin_pre(struct map_session_data **sd, uint16 *skill_id, uint16 *skill_lv) { nullpo_ret(sd); if (map->list[(*sd)->bl.m].flag.battleground && (*skill_id >= GD_SKILLBASE && *skill_id <= GD_DEVELOPMENT)) hookStop(); // Prevent original function from running after return from here. return 1; } int skillnotok_pre(uint16 *skill_id, struct map_session_data **sd) { int16 idx, m; nullpo_retr(1, *sd); m = (*sd)->bl.m; idx = skill->get_index(*skill_id); if (map->list[m].flag.battleground && (*skill_id >= GD_SKILLBASE && *skill_id <= GD_DEVELOPMENT)) { if (pc_has_permission(*sd, PC_PERM_DISABLE_SKILL_USAGE)) { hookStop(); return 1; } if (pc_has_permission(*sd, PC_PERM_SKILL_UNCONDITIONAL)) { hookStop(); return 0; // can do any damn thing they want } if ((*sd)->blockskill[idx]) { clif->skill_fail((*sd), *skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); hookStop(); return 1; } hookStop(); } return 0; } /** * Skill cast end. * @param src = source block list. * @param bl = target block list */ int skill_castend_nodamage_id_pre(struct block_list **src, struct block_list **bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { struct map_session_data *sd, *dstsd; struct status_change *tsc; struct status_data *sstatus; struct hBG_map_session_data *hBGsd = NULL; nullpo_retr(1, bl); nullpo_retr(1, src); if (!map->list[(*src)->m].flag.battleground || *skill_id != GD_EMERGENCYCALL) return 0; sd = BL_CAST(BL_PC, *src); dstsd = BL_CAST(BL_PC, *bl); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return 0; tsc = status->get_sc(*bl); sstatus = status->get_status_data(*src); switch (*skill_id) { case GD_EMERGENCYCALL: { int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; int i = 0, j = 0; struct guild *g; // i don't know if it actually summons in a circle, but oh well. ;P if (sd && (g = hBG_get_guild(sd->bg_id)) != NULL) { clif->skill_nodamage(*src, *bl, *skill_id, *skill_lv, 1); for (i = 0; i < g->max_member; i++, j++) { if (j>8) j=0; if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { if (map->getcell((*src)->m, *src, (*src)->x + dx[j], (*src)->y + dy[j], CELL_CHKNOREACH)) dx[j] = dy[j] = 0; pc->setpos(dstsd, map_id2index((*src)->m), (*src)->x+dx[j], (*src)->y+dy[j], CLR_RESPAWN); } } guild->block_skill(sd, skill->get_time2(*skill_id, *skill_lv)); } } break; case HLIF_HEAL: case AL_HEAL: { struct mob_data *dstmd = BL_UCAST(BL_MOB, *bl); int heal = skill->calc_heal(*src, *bl, *skill_id, *skill_lv, true); if (status->isimmune(*bl) || (dstmd && dstmd->class_ == MOBID_EMPELIUM)) heal = 0; if (dstmd && mob_is_battleground(dstmd)) heal = 1; if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->job&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0) heal = heal*2; if (tsc && tsc->count) { if (tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS)) { //Bounce back heal if (src == bl) heal=0; //When you try to heal yourself under Kaite, the heal is voided. else { bl = src; dstsd = sd; } } else if (tsc->data[SC_BERSERK]) { heal = 0; //Needed so that it actually displays 0 when healing. } } if (sd && dstsd && heal > 0 && sd != dstsd) { if (map->list[(*src)->m].flag.battleground && sd->bg_id && dstsd->bg_id) { if (sd->bg_id == dstsd->bg_id) add2limit(hBGsd->stats.healing_done, heal, UINT_MAX); else add2limit(hBGsd->stats.wrong_healing_done, heal, UINT_MAX); } } } break; } hookStop(); return 0; } /** * Status Pre-Hooks */ int status_get_guild_id_pre(const struct block_list **bl) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; nullpo_ret((*bl)); if ((*bl)->type == BL_PC && (bg_id = bg->team_get_id((struct block_list *)*bl)) > 0 && (bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && hBGd->g) { hookStop(); return hBGd->g->guild_id; } return 0; } int status_get_emblem_id_pre(const struct block_list **bl) { struct battleground_data *bgd; struct hBG_data *hBGd; int bg_id; nullpo_ret(bl); if ((*bl)->type == BL_PC && (bg_id = bg->team_get_id((struct block_list *)(*bl))) > 0 && (bgd = bg->team_search(bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && hBGd->g) { hookStop(); return hBGd->g->emblem_id; } return 0; } /** * Guild Pre-Hooks */ // Check if guild is null and don't run BCT checks if true. bool guild_isallied_pre(int *guild_id, int *guild_id2) { struct guild *g = guild->search(*guild_id); if (g == NULL) { hookStop(); return false; } return false; } /** * Unit Pre-Hooks */ int unit_free_pre(struct block_list **bl, clr_type *clrtype) { nullpo_retr(0, (*bl)); if ((*bl)->type == BL_PC) { struct map_session_data *sd = BL_UCAST(BL_PC, (*bl)); struct hBG_queue_data *hBGqd = NULL; struct battleground_data *bgd = NULL; struct hBG_data *hBGd = NULL; struct hBG_map_session_data *hBGsd = NULL; if ((hBGqd = getFromMSD(sd, 0)) && hBG_queue_member_search(hBGqd, sd->bl.id)) hBG_queue_member_remove(hBGqd, sd->bl.id); if (sd->bg_id != 0 && (bgd = bg->team_search(sd->bg_id)) != NULL && (hBGd = getFromBGDATA(bgd, 0)) != NULL && (hBGsd = getFromMSD(sd, 1)) != NULL) { bg->team_leave(sd, 1); hBGsd->stats.total_deserted++; } removeFromMSD(sd, 1); } return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Map Server Function Post-Hooks * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Battle Post-Hooks */ void battle_consume_ammo(struct map_session_data *sd, int skill_id, int lv) { int qty = 1; struct hBG_map_session_data *hBGsd = getFromMSD(sd, 1); if (battle->bc->arrow_decrement == 0 || hBGsd == NULL) return; if (skill) qty = max(1, skill->get_ammo_qty(skill_id, lv)); if (sd->equip_index[EQI_AMMO] >= 0) { if (sd->bg_id && map->list[sd->bl.m].flag.battleground) add2limit(hBGsd->stats.ammo_used, qty, UINT_MAX); } } // Check target immunity int battle_check_target_post(int retVal, struct block_list *src, struct block_list *target, int flag) { if (retVal == 1 && target->type == BL_MOB) { struct mob_data *md = BL_UCAST(BL_MOB, target); struct hBG_mob_data *hBGmd = NULL; if (md == NULL || (hBGmd = getFromMOBDATA(md, 0)) == NULL) return retVal; if (hBGmd != NULL && hBGmd->state.immunity) { hookStop(); return retVal; } } return retVal; } /** * Clif Post-Hooks */ void clif_parse_LoadEndAck_post(int fd, struct map_session_data *sd) { clif->charnameupdate(sd); /* Display emblem on head of char [lucaslsb] */ if (hBG_enabled && sd->state.changemap && map->list[sd->bl.m].flag.battleground) clif->map_type(sd, MAPTYPE_BATTLEFIELD); if (hBG_enabled && map->list[sd->bl.m].flag.battleground) clif->map_property(sd, MAPPROPERTY_AGITZONE); return; } //Send charname_update every time you see someone in BG void clif_getareachar_unit_post(struct map_session_data *sd, struct block_list *bl) { if (bl->type == BL_PC) { struct map_session_data *tsd = BL_CAST(BL_PC, bl); clif->charnameupdate(tsd); return; } } void clif_parse_UseSkillToId_post(int fd, struct map_session_data *sd) { uint16 skill_id; /* uint16 skill_lv; */ int target_id; const struct s_packet_db *packet = clif->packet(RFIFOW(fd,0)); struct battleground_data *bgd; struct hBG_data *hBGd; if (!sd->bg_id) return; else if ((bgd = bg->team_search(sd->bg_id)) == NULL || (hBGd = getFromBGDATA(bgd, 0)) == NULL) return; /* skill_lv = RFIFOW(fd,packet->pos[0]); */ skill_id = RFIFOW(fd,packet->pos[1]); target_id = RFIFOL(fd,packet->pos[2]); if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX && hBGd->leader_char_id == sd->status.char_id) unit->skilluse_id(&sd->bl, target_id, skill_id, guild->checkskill(hBG_get_guild(sd->bg_id), skill_id)); } /** * Server tells 'sd' player client the abouts of 'dstsd' player */ void clif_getareachar_pc_post(struct map_session_data *sd,struct map_session_data *dstsd) { if (sd->bg_id && dstsd->bg_id && sd->bg_id == dstsd->bg_id) clif->hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); } /** * PC Post hooks */ void pc_update_idle_time_post(struct map_session_data* sd, enum e_battle_config_idletime type) { struct hBG_map_session_data *hBGsd = NULL; struct battleground_data *bgd = bg->team_search(sd->bg_id); struct hBG_data *hBGd = NULL; nullpo_retv(sd); if (bgd && (hBGd = getFromBGDATA(bgd, 0)) && (hBGsd = getFromMSD(sd, 1)) && hBGsd->state.afk) { char output[256]; /* Reset AFK status */ sprintf(output, "%s : %s is no longer AFK.", sd->status.name, hBGd->g->name); hBG_send_chat_message(bgd, sd->bl.id, sd->status.name, output, (int)strlen(output) + 1); hBGsd->state.afk = 0; } } bool pc_authok_post(bool ret, struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers) { if (sd) { WFIFOHEAD(chrif->fd, 14); WFIFOW(chrif->fd, 0) = PACKET_INTER_BG_STATS_REQ; WFIFOL(chrif->fd, 2) = sd->status.account_id; WFIFOL(chrif->fd, 6) = sd->status.char_id; WFIFOL(chrif->fd, 10) = sd->fd; WFIFOSET(chrif->fd, 14); } return ret; } /** * Character Interface Post-Hooks */ /** * Requests saving of hBG Statistics and sends data to char-server. * * @param sd pointer to map session data. * @param flag as an indicator to tell char-server if character is quitting. * @return boolean. */ bool chrif_save_post(bool ret, struct map_session_data *sd, int flag) { struct hBG_map_session_data *hBGsd = NULL; int len = 13 + sizeof(struct hBG_stats); nullpo_retr(false, sd); if ((hBGsd = getFromMSD(sd, 1)) == NULL) return ret; if (flag == 1) // Logout from BG! Do not save anything. return ret; WFIFOHEAD(chrif->fd, len); WFIFOW(chrif->fd, 0) = PACKET_INTER_BG_STATS_SAVE; // 0x9000 Packet ID WFIFOL(chrif->fd, 2) = sd->status.account_id; // Account Id WFIFOL(chrif->fd, 6) = sd->status.char_id; // Char Id WFIFOB(chrif->fd, 12) = (flag==1); //Flag to tell char-server this character is quitting. memcpy(WFIFOP(chrif->fd, 13), &hBGsd->stats, sizeof(struct hBG_stats)); // hBG statistics. WFIFOSET(chrif->fd, len); return ret; } /** * Status Post Hooks */ int status_damage_post(int ret, struct block_list *src, struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) { struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; nullpo_retr(ret, target); if (src == NULL) return ret; if (src->type != BL_PC || (sd = BL_UCAST(BL_PC, src)) == NULL) return ret; if (map->list[src->m].flag.battleground == 0) return ret; if ((hBGsd = getFromMSD(sd, 1)) == NULL) return ret; hBG_record_damage(src, target, (int) in_hp); return ret; } /** * Receives and allocates map session data with bg statistics * from char-server. * * @param fd as socket descriptor handle */ void hBG_statistics_parsefromchar(int fd) { struct map_session_data *sd = NULL; struct hBG_map_session_data *hBGsd = NULL; struct hBG_stats *stats = NULL; /* int account_id = RFIFOL(fd, 2), char_id = RFIFOL(fd, 6); */ int char_fd = RFIFOL(fd,10); nullpo_retv(sockt->session[char_fd]); if ((sd = sockt->session[char_fd]->session_data) == NULL) return; if ((hBGsd = getFromMSD(sd, 1)) == NULL) { CREATE(hBGsd, struct hBG_map_session_data, 1); addToMSD(sd, hBGsd, 1, false); } if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) memcpy(&hBGsd->stats, RFIFOP(fd, 14), sizeof(struct hBG_stats)); else memcpy(&hBGsd->stats, stats, sizeof(struct hBG_stats)); } /** * Battleground Interface Overload [lucaslsb] */ /** * Remove a player from a team. * @param sd pointer to session data. * @param flag type of leave. * @return Amount of player in the BG or 0 on failure. */ int bg_team_leave_overload(struct map_session_data *sd, enum bg_team_leave_type flag) { // Single Player leaves team int i; struct battleground_data *bgd; struct hBG_map_session_data *hBGsd; struct hBG_data *hBGd; struct map_session_data *pl_sd; struct guild *g; nullpo_ret(sd); if (!sd->bg_id) return 0; else if ((hBGsd = getFromMSD(sd, 1)) == NULL) return 0; else if ((bgd = bg->team_search(sd->bg_id)) == NULL) return 0; else if ((hBGd = getFromBGDATA(bgd, 0)) == NULL) return 0; // Packets hBG_send_dot_remove(sd); // Reset information. sd->bg_id = 0; hBGsd->bg_kills = 0; // Remove battleground items if any. hBG_member_remove_bg_items(sd); // Remove Guild Skill Buffs status_change_end(&sd->bl, SC_GUILDAURA, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_BATTLEORDER, INVALID_TIMER); status_change_end(&sd->bl, SC_GDSKILL_REGENERATION, INVALID_TIMER); // Refresh Guild Information if (sd->status.guild_id && (g = guild->search(sd->status.guild_id)) != NULL) { clif->guild_belonginfo(sd, g); clif->guild_basicinfo(sd); clif->guild_allianceinfo(sd); clif->guild_memberlist(sd); clif->guild_skillinfo(sd); clif->guild_emblem(sd, g); } else { hBG_send_leave_single(sd, sd->status.name, "Leaving Battle..."); } clif->charnameupdate(sd); clif->guild_emblem_area(&sd->bl); ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == sd); if (i < MAX_BG_MEMBERS) // Removes member from BG memset(&bgd->members[i], 0, sizeof(struct battleground_member_data)); ARR_FIND(0, MAX_BG_MEMBERS, i, hBGd->g->member[i].sd == sd); if (i < MAX_BG_MEMBERS) // removes member from BG Guild memset(&hBGd->g->member[i].sd, 0, sizeof(hBGd->g->member[i].sd)); if (hBGd->leader_char_id == sd->status.char_id) hBGd->leader_char_id = 0; if (--bgd->count > 0) { for (i = 0; i < MAX_BG_MEMBERS; i++) { // Update other BG members if ((pl_sd = bgd->members[i].sd) == NULL) continue; if (!hBGd->leader_char_id) { // Set new Leader first on the list hBGd->leader_char_id = pl_sd->status.char_id; clif->charnameupdate(pl_sd); } switch (flag) { case 3: hBG_send_expulsion(pl_sd, sd->status.name, "Kicked by AFK Status..."); break; case 2: hBG_send_expulsion(pl_sd, sd->status.name, "Kicked by AFK Report..."); break; case 1: hBG_send_expulsion(pl_sd, sd->status.name, "User has quit the game..."); break; case 0: hBG_send_leave_single(pl_sd, sd->status.name, "Leaving Battle..."); break; } hBG_guild_window_info(pl_sd); hBG_send_emblem(pl_sd, hBGd->g); hBG_send_guild_member_list(pl_sd); } } if (bgd && strlen(bgd->logout_event) && flag) npc->event(sd, bgd->logout_event, 0); return bgd->count; } /** * Clif Interface Overload [lucaslsb] */ void clif_sendbgemblem_area_overload(struct map_session_data *sd) { int cmd = 0x2dd; const struct s_packet_db *packet = clif->packet(cmd); unsigned char buf[33]; nullpo_retv(sd); if (hBG_enabled) return; // Prevents display of conventional emblems WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->bl.id; safestrncpy((char*)WBUFP(buf, 6), sd->status.name, NAME_LENGTH); // name don't show in screen. WBUFW(buf, 30) = sd->bg_id; clif->send(buf, packet->len, &sd->bl, AREA); } void clif_sendbgemblem_single_overload(int fd, struct map_session_data *sd) { int cmd = 0x2dd; const struct s_packet_db *packet = clif->packet(cmd); nullpo_retv(sd); if (hBG_enabled) return; // Prevents display of conventional emblems WFIFOHEAD(fd, 32); WFIFOW(fd, 0) = cmd; WFIFOL(fd, 2) = sd->bl.id; safestrncpy(WFIFOP(fd, 6), sd->status.name, NAME_LENGTH); WFIFOW(fd, 30) = sd->bg_id; WFIFOSET(fd, packet->len); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Char Server Functions * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Character Server Saving of hBG Statistics * * @param fd socket descriptor handle */ void char_bgstats_tosql(int fd) { struct hBG_stats pstats = {0}, *stats = NULL; int account_id = 0, char_id = 0; /* int flag = 0; */ nullpo_retv(sockt->session[fd]); account_id = RFIFOL(fd, 2); char_id = RFIFOL(fd, 6); /* flag = RFIFOB(fd, 12); */ if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) { CREATE(stats, struct hBG_stats, 1); addToSession(sockt->session[fd], stats, 0, true); } memcpy(&pstats, RFIFOP(fd, 13), sizeof(struct hBG_stats)); if (memcmp(stats, &pstats, sizeof(struct hBG_stats))) { if (SQL_ERROR == SQL->Query(inter->sql_handle, "REPLACE INTO `char_bg_stats` (" "`char_id`, " "`best_damage`, `total_damage_done`, `total_damage_received`, " "`ti_wins`, `ti_lost`, `ti_tie`, " "`eos_flags`, `eos_bases`, `eos_wins`, `eos_lost`, `eos_tie`, " "`boss_killed`, `boss_damage`, `boss_flags`, `boss_wins`, `boss_lost`, `boss_tie`, " "`dom_bases`, `dom_off_kills`, `dom_def_kills`, `dom_wins`, `dom_lost`, `dom_tie`, " "`td_kills`, `td_deaths`, `td_wins`, `td_lost`, `td_tie`, " "`sc_stolen`, `sc_captured`, `sc_dropped`, `sc_wins`, `sc_lost`, `sc_tie`, " "`ctf_taken`, `ctf_captured`, `ctf_dropped`, `ctf_wins`, `ctf_lost`, `ctf_tie`, " "`emperium_kills`, `barricade_kills`, `guardian_stone_kills`, `conquest_wins`, `conquest_losses`, " "`ru_captures`, `ru_wins`, `ru_lost`, `ru_skulls`," "`kill_count`, `death_count`, `wins`, `losses`, `ties`, `wins_as_leader`, `losses_as_leader`, `ties_as_leader`, `total_deserted`, `score`, `points`, `ranked_points`, `ranked_games`," "`sp_heal_potions`, `hp_heal_potions`, `yellow_gemstones`, `red_gemstones`, `blue_gemstones`, `poison_bottles`, `acid_demostration`, `acid_demostration_fail`, " "`support_skills_used`, `healing_done`, `wrong_support_skills_used`, `wrong_healing_done`, " "`sp_used`, `zeny_used`, `spiritb_used`, `ammo_used`)" " VALUES " "('%d'," "'%d','%u','%u'," "'%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%u','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d','%d'," "'%d','%d','%d','%d','%d'," "'%d','%d','%d'," "'%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d'," "'%u','%u','%u','%u','%u','%u','%u','%u'," "'%u','%u','%u','%u'," "'%u','%u','%u','%u')", char_id, pstats.best_damage, pstats.total_damage_done, pstats.total_damage_received, pstats.ti_wins,pstats.ti_lost,pstats.ti_tie, pstats.eos_flags,pstats.eos_bases,pstats.eos_wins,pstats.eos_lost,pstats.eos_tie, pstats.boss_killed,pstats.boss_damage,pstats.boss_flags,pstats.boss_wins,pstats.boss_lost,pstats.boss_tie, pstats.dom_bases,pstats.dom_off_kills,pstats.dom_def_kills,pstats.dom_wins,pstats.dom_lost,pstats.dom_tie, pstats.td_kills,pstats.td_deaths,pstats.td_wins,pstats.td_lost,pstats.td_tie, pstats.sc_stolen,pstats.sc_captured,pstats.sc_dropped,pstats.sc_wins,pstats.sc_lost,pstats.sc_tie, pstats.ctf_taken,pstats.ctf_captured,pstats.ctf_dropped,pstats.ctf_wins,pstats.ctf_lost,pstats.ctf_tie, pstats.emperium_kills,pstats.barricade_kills,pstats.guardian_stone_kills,pstats.conquest_wins,pstats.conquest_losses, pstats.ru_captures,pstats.ru_wins,pstats.ru_lost, pstats.ru_skulls, pstats.kill_count,pstats.death_count,pstats.wins,pstats.losses,pstats.ties,pstats.wins_as_leader,pstats.losses_as_leader, pstats.ties_as_leader,pstats.total_deserted,pstats.score,pstats.points,pstats.ranked_points,pstats.ranked_games, pstats.sp_heal_potions, pstats.hp_heal_potions, pstats.yellow_gemstones, pstats.red_gemstones, pstats.blue_gemstones, pstats.poison_bottles, pstats.acid_demostration, pstats.acid_demostration_fail, pstats.support_skills_used, pstats.healing_done, pstats.wrong_support_skills_used, pstats.wrong_healing_done, pstats.sp_used, pstats.zeny_used, pstats.spiritb_used, pstats.ammo_used)) { Sql_ShowDebug(inter->sql_handle); } else { memcpy(stats, &pstats, sizeof(struct hBG_stats)); ShowInfo("Saved char (AID/CID: %d/%d) - BG Statistics [by Smokexyz].\n", account_id, char_id); } } } void char_bgstats_fromsql(int fd) { struct hBG_stats temp_stats = { 0 }, *stats = NULL; int account_id = 0, char_id = 0, char_fd = 0, len = 0; struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle); if (stmt == NULL) { SqlStmt_ShowDebug(stmt); return; } account_id = RFIFOL(fd,2); char_id = RFIFOL(fd, 6); char_fd = RFIFOL(fd, 10); if (SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT " "`best_damage`,`total_damage_done`,`total_damage_received`,`ru_skulls`,`ti_wins`,`ti_lost`,`ti_tie`,`eos_flags`,`eos_bases`,`eos_wins`," // 0-9 "`eos_lost`,`eos_tie`,`boss_killed`,`boss_damage`,`boss_flags`,`boss_wins`,`boss_lost`,`boss_tie`,`td_kills`,`td_deaths`," //10-19 "`td_wins`,`td_lost`,`td_tie`,`sc_stolen`,`sc_captured`,`sc_dropped`,`sc_wins`,`sc_lost`,`sc_tie`,`ctf_taken`," //20-29 "`ctf_captured`,`ctf_dropped`,`ctf_wins`,`ctf_lost`,`ctf_tie`,`emperium_kills`,`barricade_kills`,`guardian_stone_kills`,`conquest_wins`,`conquest_losses`,"//30-39 "`kill_count`,`death_count`,`wins`,`losses`,`ties`,`wins_as_leader`,`losses_as_leader`,`ties_as_leader`,`total_deserted`,`score`,"//40-49 "`points`,`sp_heal_potions`,`hp_heal_potions`,`yellow_gemstones`,`red_gemstones`,`blue_gemstones`,`poison_bottles`,`acid_demostration`,`acid_demostration_fail`,`support_skills_used`,"//50-59 "`healing_done`,`wrong_support_skills_used`,`wrong_healing_done`,`sp_used`,`zeny_used`,`spiritb_used`,`ammo_used`,`ranked_points`,`ranked_games`,`ru_wins`,"//60-69 "`ru_lost`,`ru_captures`,`dom_bases`,`dom_off_kills`,`dom_def_kills`,`dom_wins`,`dom_lost`,`dom_tie`"//70-79 " FROM `char_bg_stats` WHERE `char_id` = ?") || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, sizeof char_id) || SQL_ERROR == SQL->StmtExecute(stmt) || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_UINT, &temp_stats.best_damage, sizeof temp_stats.best_damage, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UINT, &temp_stats.total_damage_done, sizeof temp_stats.total_damage_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_UINT, &temp_stats.total_damage_received, sizeof temp_stats.total_damage_received, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &temp_stats.ru_skulls, sizeof temp_stats.ru_skulls, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_USHORT, &temp_stats.ti_wins, sizeof temp_stats.ti_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_USHORT, &temp_stats.ti_lost, sizeof temp_stats.ti_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_USHORT, &temp_stats.ti_tie, sizeof temp_stats.ti_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_USHORT, &temp_stats.eos_flags, sizeof temp_stats.eos_flags, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_USHORT, &temp_stats.eos_bases, sizeof temp_stats.eos_bases, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_USHORT, &temp_stats.eos_wins, sizeof temp_stats.eos_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_USHORT, &temp_stats.eos_lost, sizeof temp_stats.eos_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_USHORT, &temp_stats.eos_tie, sizeof temp_stats.eos_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 12, SQLDT_USHORT, &temp_stats.boss_killed, sizeof temp_stats.boss_killed, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 13, SQLDT_UINT, &temp_stats.boss_damage, sizeof temp_stats.boss_damage, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 14, SQLDT_USHORT, &temp_stats.boss_flags, sizeof temp_stats.boss_flags, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 15, SQLDT_USHORT, &temp_stats.boss_wins, sizeof temp_stats.boss_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 16, SQLDT_USHORT, &temp_stats.boss_lost, sizeof temp_stats.boss_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 17, SQLDT_USHORT, &temp_stats.boss_tie, sizeof temp_stats.boss_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 18, SQLDT_USHORT, &temp_stats.td_kills, sizeof temp_stats.td_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 19, SQLDT_USHORT, &temp_stats.td_deaths, sizeof temp_stats.td_deaths, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 20, SQLDT_USHORT, &temp_stats.td_wins, sizeof temp_stats.td_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 21, SQLDT_USHORT, &temp_stats.td_lost, sizeof temp_stats.td_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 22, SQLDT_USHORT, &temp_stats.td_tie, sizeof temp_stats.td_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 23, SQLDT_USHORT, &temp_stats.sc_stolen, sizeof temp_stats.sc_stolen, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 24, SQLDT_USHORT, &temp_stats.sc_captured, sizeof temp_stats.sc_captured, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 25, SQLDT_USHORT, &temp_stats.sc_dropped, sizeof temp_stats.sc_dropped, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 26, SQLDT_USHORT, &temp_stats.sc_wins, sizeof temp_stats.sc_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 27, SQLDT_USHORT, &temp_stats.sc_lost, sizeof temp_stats.sc_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 28, SQLDT_USHORT, &temp_stats.sc_tie, sizeof temp_stats.sc_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 29, SQLDT_USHORT, &temp_stats.ctf_taken, sizeof temp_stats.ctf_taken, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 30, SQLDT_USHORT, &temp_stats.ctf_captured, sizeof temp_stats.ctf_captured, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 31, SQLDT_USHORT, &temp_stats.ctf_dropped, sizeof temp_stats.ctf_dropped, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 32, SQLDT_USHORT, &temp_stats.ctf_wins, sizeof temp_stats.ctf_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 33, SQLDT_USHORT, &temp_stats.ctf_lost, sizeof temp_stats.ctf_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 34, SQLDT_USHORT, &temp_stats.ctf_tie, sizeof temp_stats.ctf_tie, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_USHORT, &temp_stats.emperium_kills, sizeof temp_stats.emperium_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_USHORT, &temp_stats.barricade_kills, sizeof temp_stats.barricade_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_USHORT, &temp_stats.guardian_stone_kills, sizeof temp_stats.guardian_stone_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_USHORT, &temp_stats.conquest_wins, sizeof temp_stats.conquest_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 39, SQLDT_USHORT, &temp_stats.conquest_losses, sizeof temp_stats.conquest_losses, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 40, SQLDT_USHORT, &temp_stats.kill_count, sizeof temp_stats.kill_count, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 41, SQLDT_USHORT, &temp_stats.death_count, sizeof temp_stats.death_count, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 42, SQLDT_USHORT, &temp_stats.wins, sizeof temp_stats.wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 43, SQLDT_USHORT, &temp_stats.losses, sizeof temp_stats.losses, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 44, SQLDT_USHORT, &temp_stats.ties, sizeof temp_stats.ties, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 45, SQLDT_USHORT, &temp_stats.wins_as_leader, sizeof temp_stats.wins_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 46, SQLDT_USHORT, &temp_stats.losses_as_leader, sizeof temp_stats.losses_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 47, SQLDT_USHORT, &temp_stats.ties_as_leader, sizeof temp_stats.ties_as_leader, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 48, SQLDT_USHORT, &temp_stats.total_deserted, sizeof temp_stats.total_deserted, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 49, SQLDT_INT, &temp_stats.score, sizeof temp_stats.score, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 50, SQLDT_INT, &temp_stats.points, sizeof temp_stats.points, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 51, SQLDT_UINT, &temp_stats.sp_heal_potions, sizeof temp_stats.sp_heal_potions, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 52, SQLDT_UINT, &temp_stats.hp_heal_potions, sizeof temp_stats.hp_heal_potions, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &temp_stats.yellow_gemstones, sizeof temp_stats.yellow_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UINT, &temp_stats.red_gemstones, sizeof temp_stats.red_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &temp_stats.blue_gemstones, sizeof temp_stats.blue_gemstones, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_UINT, &temp_stats.poison_bottles, sizeof temp_stats.poison_bottles, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 57, SQLDT_UINT, &temp_stats.acid_demostration, sizeof temp_stats.acid_demostration, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 58, SQLDT_UINT, &temp_stats.acid_demostration_fail, sizeof temp_stats.acid_demostration_fail, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 59, SQLDT_UINT, &temp_stats.support_skills_used, sizeof temp_stats.support_skills_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 60, SQLDT_UINT, &temp_stats.healing_done, sizeof temp_stats.healing_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 61, SQLDT_UINT, &temp_stats.wrong_support_skills_used, sizeof temp_stats.wrong_support_skills_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 62, SQLDT_UINT, &temp_stats.wrong_healing_done, sizeof temp_stats.wrong_healing_done, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 63, SQLDT_UINT, &temp_stats.sp_used, sizeof temp_stats.sp_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 64, SQLDT_UINT, &temp_stats.zeny_used, sizeof temp_stats.zeny_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 65, SQLDT_UINT, &temp_stats.spiritb_used, sizeof temp_stats.spiritb_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 66, SQLDT_UINT, &temp_stats.ammo_used, sizeof temp_stats.ammo_used, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 67, SQLDT_UINT, &temp_stats.ranked_points, sizeof temp_stats.ranked_points, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 68, SQLDT_USHORT, &temp_stats.ranked_games, sizeof temp_stats.ranked_games, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 69, SQLDT_USHORT, &temp_stats.ru_wins, sizeof temp_stats.ru_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 70, SQLDT_USHORT, &temp_stats.ru_lost, sizeof temp_stats.ru_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 71, SQLDT_USHORT, &temp_stats.ru_captures, sizeof temp_stats.ru_captures, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 72, SQLDT_USHORT, &temp_stats.dom_bases, sizeof temp_stats.dom_bases, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 73, SQLDT_USHORT, &temp_stats.dom_off_kills, sizeof temp_stats.dom_off_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 74, SQLDT_USHORT, &temp_stats.dom_def_kills, sizeof temp_stats.dom_def_kills, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 75, SQLDT_USHORT, &temp_stats.dom_wins, sizeof temp_stats.dom_wins, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 76, SQLDT_USHORT, &temp_stats.dom_lost, sizeof temp_stats.dom_lost, NULL, NULL) || SQL_ERROR == SQL->StmtBindColumn(stmt, 77, SQLDT_USHORT, &temp_stats.dom_tie, sizeof temp_stats.dom_tie, NULL, NULL) || SQL_SUCCESS != SQL->StmtNextRow(stmt)) { temp_stats.score = 2000; } ShowInfo("Loaded char (AID/CID: %d/%d) - BG Statistics [by Smokexyz]\n", account_id, char_id); if ((stats = getFromSession(sockt->session[fd], 0)) == NULL) { CREATE(stats, struct hBG_stats, 1); memcpy(stats, &temp_stats, sizeof(struct hBG_stats)); addToSession(sockt->session[fd], stats, 0, true); } else if (memcmp(stats, &temp_stats, sizeof(struct hBG_stats))) { memcpy(stats, &temp_stats, sizeof(struct hBG_stats)); } SQL->StmtFree(stmt); len = 14 + sizeof(struct hBG_stats); WFIFOHEAD(fd, len); WFIFOW(fd, 0) = PACKET_MAP_BG_STATS_GET; WFIFOL(fd, 2) = account_id; WFIFOL(fd, 6) = char_id; WFIFOL(fd, 10) = char_fd; memcpy(WFIFOP(fd, 14), &temp_stats, sizeof(struct hBG_stats)); WFIFOSET(fd, len); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Battle Configuration Parsing * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void hBG_config_read(const char *key, const char *val) { int value = config_switch (val); if (strcmpi(key,"battle_configuration/hBG_enabled") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_enabled, defaulting to 0.\n", value); return; } hBG_enabled = value; } else if (strcmpi(key, "battle_configuration/hBG_from_town_only") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_from_town_only, defaulting to 0.\n", value); return; } hBG_from_town_only = value; } else if (strcmpi(key, "battle_configuration/hBG_ip_check") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_ip_check, defaulting to 0.\n", value); return; } hBG_ip_check = value; } else if (strcmpi(key, "battle_configuration/hBG_idle_announce") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_idle_announce, defaulting to 60 seconds.\n", value); hBG_idle_announce = 60; } else { hBG_idle_announce = value; } } else if (strcmpi(key, "battle_configuration/hBG_idle_autokick") == 0) { if (value < 0) { ShowWarning("Received Invalid Setting %d for hBG_idle_autokick, defaulting to 5 minutes (300s).\n", value); hBG_idle_autokick = 300; } else { hBG_idle_autokick = value; } } else if (strcmpi(key, "battle_configuration/hBG_reportafk_leaderonly") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_reportafk_leaderonly, defaulting to 0.\n", value); hBG_reportafk_leaderonly = 0; } else { hBG_reportafk_leaderonly = value; } } else if (strcmpi(key, "battle_configuration/hBG_balanced_queue") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_balanced_queue, defaulting to 0.\n", value); return; } hBG_balanced_queue = value; } else if (strcmpi(key, "battle_configuration/hBG_reward_rates") == 0) { if (value < 0) { ShowWarning("Received invalid setting %d for hBG_reward_rates, defaulting to 100.\n", value); hBG_reward_rates = 100; } else { hBG_reward_rates = value; } } else if (strcmpi(key, "battle_configuration/hBG_xy_interval") == 0) { if (value < 1000) { ShowWarning("Received Invalid Setting %d for hBG_xy_interval. (min: %d, max: %d) Defaulting to 1000ms. \n", value, 1000, INT_MAX); hBG_xy_interval = 1000; } else { hBG_xy_interval = value; } } else if (strcmpi(key, "battle_configuration/hBG_ranked_mode") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_ranked_mode, defaulting to 0.\n", value); hBG_ranked_mode = 0; } else { hBG_ranked_mode = value; } } else if (strcmpi(key, "battle_configuration/hBG_leader_change") == 0) { if (value < 0 || value > 1) { ShowWarning("Received Invalid Setting %d for hBG_leader_change, defaulting to 0.\n", value); hBG_leader_change = 0; } else { hBG_leader_change = value; } } } int hBG_config_get(const char *key) { if (strcmpi(key, "battle_configuration/hBG_enabled") == 0) return hBG_enabled; else if (strcmpi(key, "battle_configuration/hBG_from_town_only") == 0) return hBG_from_town_only; else if (strcmpi(key, "battle_configuration/hBG_ip_check") == 0) return hBG_ip_check; else if (strcmpi(key, "battle_configuration/hBG_idle_announce") == 0) return hBG_idle_announce; else if (strcmpi(key, "battle_configuration/hBG_idle_autokick") == 0) return hBG_idle_autokick; else if (strcmpi(key, "battle_configuration/hBG_reportafk_leaderonly") == 0) return hBG_reportafk_leaderonly; else if (strcmpi(key, "battle_configuration/hBG_balanced_queue") == 0) return hBG_balanced_queue; else if (strcmpi(key, "battle_configuration/hBG_reward_rates") == 0) return hBG_reward_rates; else if (strcmpi(key, "battle_configuration/hBG_xy_interval") == 0) return hBG_xy_interval; else if (strcmpi(key, "battle_configuration/hBG_ranked_mode") == 0) return hBG_ranked_mode; else if (strcmpi(key, "battle_configuration/hBG_leader_change") == 0) return hBG_leader_change; return 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Plugin Handling * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* run when server starts */ HPExport void plugin_init(void) { int interval = hBG_config_get("battle_configuration/hBG_xy_interval"); if (SERVER_TYPE == SERVER_TYPE_CHAR) { addPacket(PACKET_INTER_BG_STATS_REQ, 14, char_bgstats_fromsql, hpParse_FromMap); addPacket(PACKET_INTER_BG_STATS_SAVE, 13 + sizeof(struct hBG_stats), char_bgstats_tosql, hpParse_FromMap); } if (SERVER_TYPE == SERVER_TYPE_MAP) { addPacket(PACKET_MAP_BG_STATS_GET, 14+sizeof(struct hBG_stats), hBG_statistics_parsefromchar, hpChrif_Parse); /* Function Pre-Hooks */ addHookPre(npc, parse_unknown_mapflag, npc_parse_unknown_mapflag_pre); addHookPre(clif, charnameupdate, clif_charnameupdate_pre); addHookPre(clif, pGuildRequestInfo,clif_parse_GuildRequestInfo_pre); addHookPre(status, get_guild_id, status_get_guild_id_pre); addHookPre(status, get_emblem_id, status_get_emblem_id_pre); addHookPre(guild, isallied, guild_isallied_pre); addHookPre(skill, check_condition_castbegin, skill_check_condition_castbegin_pre); addHookPre(skill, not_ok, skillnotok_pre); addHookPre(skill, castend_nodamage_id, skill_castend_nodamage_id_pre); addHookPre(unit, free, unit_free_pre); /* Function Post-Hooks */ addHookPost(clif, pLoadEndAck, clif_parse_LoadEndAck_post); addHookPost(clif, pUseSkillToId, clif_parse_UseSkillToId_post); addHookPost(clif, getareachar_pc, clif_getareachar_pc_post); addHookPost(clif, getareachar_unit, clif_getareachar_unit_post); addHookPost(pc, update_idle_time, pc_update_idle_time_post); addHookPost(pc, authok, pc_authok_post); addHookPost(chrif, save, chrif_save_post); addHookPost(status, damage, status_damage_post); addHookPost(battle, check_target, battle_check_target_post); /* @Commands */ addAtcommand("bgrank", bgrank); addAtcommand("reportafk", reportafk); addAtcommand("leader", leader); /* Script Commands */ addScriptCommand("hBG_team_create","siiiss", hBG_team_create); addScriptCommand("hBG_queue_create","ss?", hBG_queue_create); addScriptCommand("hBG_queue_event","is", hBG_queue_event); addScriptCommand("hBG_queue_join","i", hBG_queue_join); addScriptCommand("hBG_queue_partyjoin","ii", hBG_queue_partyjoin); addScriptCommand("hBG_queue_leave","i", hBG_queue_leave); addScriptCommand("hBG_queue_data","ii", hBG_queue_data); addScriptCommand("hBG_queue2team","iisiiiss", hBG_queue2team); addScriptCommand("hBG_queue2team_single","iisii", hBG_queue2team_single); addScriptCommand("hBG_queue2teams","iiiiii*", hBG_queue2teams); addScriptCommand("hBG_queue_checkstart","iiii", hBG_queue_checkstart); addScriptCommand("hBG_balance_teams","iiiii*", hBG_balance_teams); addScriptCommand("hBG_waitingroom2bg","siiiss", hBG_waitingroom2bg); addScriptCommand("hBG_waitingroom2bg_single","isiis", hBG_waitingroom2bg_single); addScriptCommand("hBG_team_setxy","iii", hBG_team_setxy); addScriptCommand("hBG_team_reveal","i", hBG_team_reveal); addScriptCommand("hBG_team_conceal","i", hBG_team_conceal); addScriptCommand("hBG_team_setquest","ii", hBG_team_setquest); addScriptCommand("hBG_viewpointmap","siiiii", hBG_viewpointmap); addScriptCommand("hBG_monster_reveal","iii", hBG_monster_reveal); addScriptCommand("hBG_monster_set_team","ii", hBG_monster_set_team); addScriptCommand("hBG_monster_immunity","ii", hBG_monster_immunity); addScriptCommand("hBG_leave","", hBG_leave); addScriptCommand("hBG_destroy","i", hBG_destroy); addScriptCommand("hBG_clean","i", hBG_clean); addScriptCommand("hBG_get_data","ii", hBG_get_data); addScriptCommand("hBG_getareausers","isiiii", hBG_getareausers); addScriptCommand("hBG_updatescore","sii", hBG_updatescore); addScriptCommand("hBG_team_updatescore", "ii", hBG_update_score_team); addScriptCommand("hBG_team_guildid","i", hBG_get_team_gid); addScriptCommand("hBG_getitem","iii", hBG_getitem); addScriptCommand("hBG_getkafrapoints","ii", hBG_getkafrapoints); addScriptCommand("hBG_reward","iiiiisiii", hBG_reward); addScriptCommand("hBG_flooritem2xy", "siiii", hBG_flooritem2xy); addScriptCommand("hBG_warp", "isii", hBG_warp); hBG_queue_db = idb_alloc(DB_OPT_RELEASE_DATA); timer->add_func_list(hBG_send_xy_timer, "hBG_send_xy_timer"); timer->add_interval(timer->gettick() + interval , hBG_send_xy_timer, 0, 0, interval); } } /* triggered when server starts loading, before any server-specific data is set */ HPExport void server_preinit(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { addBattleConf("battle_configuration/hBG_enabled", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_from_town_only", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_ip_check", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_idle_announce", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_idle_autokick", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_balanced_queue", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_reward_rates", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_xy_interval", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_ranked_mode", hBG_config_read, hBG_config_get, true); addBattleConf("battle_configuration/hBG_leader_change", hBG_config_read, hBG_config_get, true); } } /* run when server is ready (online) */ HPExport void server_online(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { hBG_build_guild_data(); ShowStatus("%s v%s has been initialized. [by Smokexyz]\n", pinfo.name, pinfo.version); // clif interface overloading [lucaslsb] bg->team_leave = &bg_team_leave_overload; clif->sendbgemblem_area = &clif_sendbgemblem_area_overload; clif->sendbgemblem_single = &clif_sendbgemblem_single_overload; } } static int queue_db_final(union DBKey key, struct DBData *data, va_list ap) { struct hBG_queue_data *hBGqd = DB->data2ptr(data); if (hBGqd) hBG_queue_members_finalize(hBGqd); // Unlink all queue members return 0; } /* run when server is shutting down */ HPExport void plugin_final(void) { if (SERVER_TYPE == SERVER_TYPE_MAP) { hBG_queue_db->destroy(hBG_queue_db, queue_db_final); ShowInfo ("%s v%s has been finalized. [by Smokexyz]\n", pinfo.name, pinfo.version); } } hBG.c: In function ‘atcommand_reportafk’: hBG.c:2040:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘atcommand_leader’: hBG.c:2084:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘status_get_guild_id_pre’: hBG.c:3776:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)*bl)) > 0 ^ hBG.c: In function ‘status_get_emblem_id_pre’: hBG.c:3797:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)(*bl))) > 0 ^ PLUGIN hBG Using this plugin. You are using an old hBG.c Use the one from this link: https://github.com/lucasljsb/HerculesBG/blob/50a1a3963fe2590a787aab27b27fa2faf9e1f277/src/plugins/hBG.c Quote Share this post Link to post Share on other sites
Good day!
Help me how to correct these warnings please.
hBG.c: In function ‘atcommand_reportafk’: hBG.c:2040:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘atcommand_leader’: hBG.c:2084:31: warning: unused variable ‘hBGsd’ [-Wunused-variable] struct hBG_map_session_data *hBGsd = NULL; ^ hBG.c: In function ‘status_get_guild_id_pre’: hBG.c:3776:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)*bl)) > 0 ^ hBG.c: In function ‘status_get_emblem_id_pre’: hBG.c:3797:31: warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual] && (bg_id = bg->team_get_id((struct block_list *)(*bl))) > 0 ^ PLUGIN hBG
Using this plugin.
use [spoiler]+[code] tag when posting script > 10 lines
Share this post
Link to post
Share on other sites