MikZ
-
Content Count
461 -
Joined
-
Last visited
Posts posted by MikZ
-
-
2 hours ago, meko said:change end; to return; on lines 96 and 111
Hi @meko i did change as advised. Yet, it allows me to warp to renewal map instead of restricting for Pre-Re
function Pick { .@warp_block = @warp_block; @warp_block = 0; .@select = select(@menu$); if (getarg(0) == "") { .@i = .@select; .@map$ = getarg(.@i); } else { .@i = .@select-getarg(1,0); .@map$ = getarg(0)+((.@i<10)?"0":"")+.@i; } if (.@warp_block & (1<<.@select)) { message strcharinfo(PC_NAME),"This map is not enabled in "+(RENEWAL?"":"Pre-")+"Renewal."; return; } .@x = @c[.@i*2]; .@y = @c[.@i*2+1]; deletearray @c[0],getarraysize(@c); Go(.@map$,.@x,.@y); } function Restrict { if ((getarg(0) == "RE" && !RENEWAL) || (getarg(0) == "Pre-RE" && RENEWAL)) { if (getarg(1,0)) { @warp_block = 0; for (.@i = 1; .@i < getargcount(); .@i++) @warp_block = @warp_block | (1<<getarg(.@i)); } else { message strcharinfo(PC_NAME),"This map is not enabled in "+(RENEWAL?"":"Pre-")+"Renewal."; return; } } return; }
-
Good day!
I don't know if this has been address or what, but if you happen to choose the Renewal Maps in the NPC warper a message will appear:" message strcharinfo(0),"This map is not enabled in "+((RENEWAL)?"":"Pre-")+"Renewal.";"
However, after the receiving the message you won't be able to move nor to click on NPCs, you need to @refresh or relog.
How to fix this? thanks! -
Good day!
How/where can i edit this table margin to place it inside (center) the main table? thanks! -
thank you! I thought Showing of player names can only be done thru SQL QUERIES.
-
Good day Master Scripters,
Requesting a script for race to 99/70 event for all trans job:
NPC Features:-
NPC will let players know who won the race to 99/70 or was it still availble per job.
-
Switch ("FIRST 99ners")
- LORD KNIGHT : PLAYER NAME 1
- HIGH WIZARD : PLAYER NAME 2
- HUNTER : <NONE> (Meaning slot is still available)
- HIGH PRIEST: <NONE>
-
Switch ("FIRST 99ners")
-
Once reach 99/70 World Announce :
- Lord Knight Player Name 1 has reached the maximum level(For lord knight Job)
- High Wizard Player Name 2 so on and so fort.
- Guess that's all i need will just give the prize manual trade for picture taking purposes.
-
NPC will let players know who won the race to 99/70 or was it still availble per job.
-
Good day!
Requesting for guide how to update fluxcp.
I tried the theme uploaded by Plug and Play but seems it not compatible to the current emulator anymore .
Or was this being address? thanks!
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Markdown_Parser has a deprecated constructor in /homepages/19/d739599868/htdocs/LibRO/lib/markdown/markdown.php on line 215 Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; MarkdownExtra_Parser has a deprecated constructor in /homepages/19/d739599868/htdocs/LibRO/lib/markdown/markdown.php on line 1677 Strict Standards: date(): We selected 'America/New_York' for 'EDT/-4.0/DST' instead in /homepages/19/d739599868/htdocs/LibRO/lib/Flux/Connection/Statement.php on line 14 Strict Standards: date(): We selected 'America/New_York' for 'EDT/-4.0/DST' instead in /homepages/19/d739599868/htdocs/LibRO/lib/Flux/LogFile.php on line 74
-
21 hours ago, AnnieRuru said:the script you posted made by me ...
sorry as I don't own Gepard, I don't know how it works so I couldn't make this system for youand what meko said was spot on,
just reminded the IP address detection method on this script can just bypass by restarting the modemthe mac address system though ...
sry maybe I was out from RO scene too long ?
2 years ago I heard that mac address is something that is only possible by adding a 3rd party program running in the background ...and this makes me assume that Gepard is also something 3rd party program ... stuffs
@AnnieRuru its okay.
I somehow just edit it with the common query command and change the ip to unique_id. Somehow it worked fine for daily login.
Wonder if you have any suggestion or tips to improve this. I don't kinda understand the script cuz im noob. but that this mean every 00:00 server time you will be able to get coin or 24hr from last talked to the npc?prontera,164,173,5 script Daily Login 4_F_FAIRYKID4,{ // $ip_reward_daytime = 0; query_sql("SELECT `last_unique_id` from `login` WHERE `account_id` = "+getcharid(3),@lui$); mes "["+ strnpcinfo(NPC_NAME) +"]"; if ( $ip_reward_daytime != atoi( gettimestr("%Y%m%d", 20 ) ) ) { $ip_reward_daytime = atoi( gettimestr("%Y%m%d", 20 ) ); deletearray $ip_reward$; } .@size = getarraysize( $ip_reward$ ); while ( @lui$ != $ip_reward$[.@i] && .@i < .@size ) { ++.@i; } if ( .@i < .@size ) { mes "You have claimed the reward."; close; } if ( @ip_reward && @ip_reward + .countdown <= gettimetick(2) ) { mes "Here is the surprise reward"; getitem 25045, 1; $ip_reward$[ getarraysize( $ip_reward$ ) ] = @lui$; close; } if ( @ip_reward ) { mes "Countdown timer..."; .@timeleft = @ip_reward + .countdown - gettimetick(2); mes .@timeleft /3600 +" hour "+ .@timeleft %3600/60 +" min "+ .@timeleft %60 +" sec left"; close; } mes "Hello "+ strcharinfo(PC_NAME) +", I am here to give you a daily Surprise Reward. Do you want to have it?"; next; select "Yes, sure !!"; mes "["+ strnpcinfo(NPC_NAME) +"]"; mes "You can claim the reward after an hour."; close2; addtimer .countdown *1000, strnpcinfo(NPC_NAME) +"::OnClaimReward"; @ip_reward = gettimetick(2); end; OnClaimReward: dispbottom "You can claim Daily Login Reward now."; end; OnInit: .countdown = 1*60*60; // 5 hours // .countdown = 5; }
-
Anyone please?
how to change getcharip() to getcharuniqueid() (gepard) -
2 hours ago, meko said:IP addresses and mac addresses do not uniquely identify people. Most home internet users have dynamic IP addresses assigned by their ISP, so it changes over time, and some ISPs even assign a different one every single time the router is rebooted (ie: Orange). Even with a static IP, nothing prevents anyone from using a VPN, tor, or any other anonymity tool. IP addresses may also be shared: some schools, dormitories, and organizations have a single address for every single computer on its network, so you could end up mistaking hundreds of people as the same person. Some computers themselves are also shared (ie: with coworkers, family members, friends, …). As for mac addresses, they can very easily be spoofed, and one could even make a script to change their mac address every minute if they wanted to... so yeah, that's a bad idea too.
If this still does not discourage you from using mac addresses, feel free to add this "feature" to Hercules: https://github.com/HerculesWS/Hercules/issues/1734
There's really no silver bullet to really be sure of the identity of someone, but one of the approaches that kinda works is to make abuse costly on abusers, while not imposing a huge burden on non-abusers. What works best is doing a physical verification instead of a digital one when someone creates an account. For example, most social media platforms now ask you to provide and validate a phone number. This means if someone were to bypass this verification they would have to have more than one phone. Some sites, such as Paypal, go even further ask you for your credit card number (or bank account number) and then do a transaction on it (usually $1), to see if the card is valid. This means you would have to have more than one credit card if you want to bypass this verification, which implies physically going to your bank, making an appointment, and opening a new account. Some (such as Google) prefer to snail mail you an envelope containing a code, which you then have to enter on their website. To abuse this you would need more than one street address. Keep in mind that this only makes it harder on would-be abusers and that nothing can 100% fingerprint someone. Even DNA profiling isn't perfect.
Thank you for this @meko. I am planning to buy gepard. How about gepard last_unique_id is it changeable?
May I know how to change the script from last_ip to last_unique_id? thanks! -
On 5/24/2018 at 10:55 PM, AnnieRuru said:prontera,155,180,5 script Reward NPC 4_F_FAIRYKID4,{ // $ip_reward_daytime = 0; mes "["+ strnpcinfo(NPC_NAME) +"]"; if ( $ip_reward_daytime != atoi( gettimestr("%Y%m%d", 20 ) ) ) { $ip_reward_daytime = atoi( gettimestr("%Y%m%d", 20 ) ); deletearray $ip_reward$; } .@size = getarraysize( $ip_reward$ ); while ( getcharip() != $ip_reward$[.@i] && .@i < .@size ) { ++.@i; } if ( .@i < .@size ) { mes "You have claimed the reward with this IP address."; close; } if ( @ip_reward && @ip_reward + .countdown <= gettimetick(2) ) { mes "Here is the surprise reward"; getitem Poring_Coin, 1; $ip_reward$[ getarraysize( $ip_reward$ ) ] = getcharip(); close; } if ( @ip_reward ) { mes "Countdown timer..."; .@timeleft = @ip_reward + .countdown - gettimetick(2); mes .@timeleft /3600 +" hour "+ .@timeleft %3600/60 +" min "+ .@timeleft %60 +" sec left"; close; } mes "Hello "+ strcharinfo(PC_NAME) +", I am here to give you a daily Surprise Reward. Do you want to have it?"; next; select "Yes, sure !!"; mes "["+ strnpcinfo(NPC_NAME) +"]"; mes "You can claim the reward in 5 hours time."; close2; addtimer .countdown *1000, strnpcinfo(NPC_NAME) +"::OnClaimReward"; @ip_reward = gettimetick(2); end; OnClaimReward: dispbottom "You can claim Daily Login Reward now."; end; OnInit: .countdown = 5*60*60; // 5 hours // .countdown = 5; }
@AnnieRuru how can i change getcharip() to last_mac or last_unique_id?
-
I already post this request when I found out someone someone already requested with same script.
Wanted to know how to change to last_mac.prontera,155,180,5 script Reward NPC 4_F_FAIRYKID4,{ // $ip_reward_daytime = 0; mes "["+ strnpcinfo(NPC_NAME) +"]"; if ( $ip_reward_daytime != atoi( gettimestr("%Y%m%d", 20 ) ) ) { $ip_reward_daytime = atoi( gettimestr("%Y%m%d", 20 ) ); deletearray $ip_reward$; } .@size = getarraysize( $ip_reward$ ); while ( getcharip() != $ip_reward$[.@i] && .@i < .@size ) { ++.@i; } if ( .@i < .@size ) { mes "You have claimed the reward with this IP address."; close; } if ( @ip_reward && @ip_reward + .countdown <= gettimetick(2) ) { mes "Here is the surprise reward"; getitem Poring_Coin, 1; $ip_reward$[ getarraysize( $ip_reward$ ) ] = getcharip(); close; } if ( @ip_reward ) { mes "Countdown timer..."; .@timeleft = @ip_reward + .countdown - gettimetick(2); mes .@timeleft /3600 +" hour "+ .@timeleft %3600/60 +" min "+ .@timeleft %60 +" sec left"; close; } mes "Hello "+ strcharinfo(PC_NAME) +", I am here to give you a daily Surprise Reward. Do you want to have it?"; next; select "Yes, sure !!"; mes "["+ strnpcinfo(NPC_NAME) +"]"; mes "You can claim the reward in 5 hours time."; close2; addtimer .countdown *1000, strnpcinfo(NPC_NAME) +"::OnClaimReward"; @ip_reward = gettimetick(2); end; OnClaimReward: dispbottom "You can claim Daily Login Reward now."; end; OnInit: .countdown = 5*60*60; // 5 hours // .countdown = 5; }
-
Hi Ms. @AnnieRuru I really like the idea. i know this is just a sample but mind if i ask if possible or is it possible; how
-
to make this DAILY chain quest. - to make this every 00:00 server time this quest reset back to zero 0. Player should finish the quest before 00:00
- and if player finishes the quest before 00:00 then player took a quest again will remind that need to wait for --:-- hours until quest reset at 00:00.
- Regardless if player only reach mission 2, quest will reset back to 0 once 00:00.
-
to Place item reward or exp reward per npc mission accomplish(guess this can added in after "dispbottom "mission 1 pass";") -
quest depend per base level "1-20","21-40","41-60","61-80","81-99".
Thanks!
-
-
2 hours ago, AnnieRuru said:assuming you have this https://github.com/HerculesWS/Hercules/blob/stable/npc/mapflag/town.txt
prontera,150,185,5 script test 1_F_MARIA,{ input .@map$; if ( getmapusers( .@map$ ) == -1 ) dispbottom "no such map"; else if ( !getmapflag( .@map$, mf_town ) ) dispbottom "not a town"; else atcommand "@go "+ .@map$; // yeah lazy to note down the coordinate, so use atcommand end; }
Thank you so much Ms. AnnieRuru!!!
-
Good day!
May I request a script in consumable items to allow players to warp to a town.
wanted to have it like @go not @warp to player can just input town number or name. no dungeon or field. strictly for town warp.
Thanks!Script: <" input .@map$; if ( getmapusers( .@map$ ) != -1 ) warp .@map$,0,0; end; "> },
-
On 4/5/2017 at 6:43 PM, tedexx said:map_index.txt
// Haunt haunt_e haunt_h 1@haunt 2@haunt
conf/map/maps.conf
// Haunt "haunt_e", "haunt_h", "1@haunt", "2@haunt",
resnametable
1@haunt.gnd#haunt_e.gnd# 1@haunt.gat#haunt_e.gat# 1@haunt.rsw#haunt_e.rsw# 유저인터페이스\map\1@haunt.bmp#유저인터페이스\map\blank.bmp# 2@haunt.gnd#haunt_h.gnd# 2@haunt.gat#haunt_h.gat# 2@haunt.rsw#haunt_h.rsw# 유저인터페이스\map\1@haunt.bmp#유저인터페이스\map\blank.bmp#
All files added to map_cache.dat and yet I'm still having problems. I had this problem before trying to use one map as same as another and wasn't able to make it work. Just don't get how it works.
Ignoring the map problem, this occurs when starting the solo option (only one tested)
Got the same ERROR.
Any update?
Tried to ignore error and i got this. /sob[Debug]: script debug : 2000000 110137260 : Attempting to create Instance. [Debug]: script debug : 2000000 110137260 : Attempt successful on Instance attach! [Debug]: script debug : 0 110139933 : [Floor] # 1 :: [Total mobs] : 5 [Debug]: script debug : 0 110139933 : [Floor] # 2 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : [Floor] # 3 :: [Total mobs] : 6 [Debug]: script debug : 0 110139933 : [Floor] # 4 :: [Total mobs] : 5 [Debug]: script debug : 0 110139933 : [Floor] # 5 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : [Floor] # 6 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : [Floor] # 7 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : [Floor] # 8 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : [Floor] # 9 :: [Total mobs] : 6 [Debug]: script debug : 0 110139933 : [Floor] # 10 :: [Total mobs] : 7 [Debug]: script debug : 0 110139933 : 64 Total mobs. [Error]: script:instance_npcname: invalid instance NPC (instance_id: 0, NPC name: "Hidden Key#1".) [Debug]: Source (NPC): InstanceBegin#Ins at 000#1@haunt (1,4) [Info]: Saved char 150001 - DarK: status skills.
-
23 hours ago, AnnieRuru said:script -> http://upaste.me/94e94979017edd8ef
plugin -> http://upaste.me/d74c497892f91a6d6@MikZ next time should ask on the forum instead of bombard my PM box
and its your own topic tooThanks you so much! Sorry if I PMd you.. /no1
-
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.
-
Someone please help.
How to solve these warnings.
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
-
Any update?
-
Thanks!
-
Good day!
Where did the maxcount went? I wanted to limit number of specific skill in land like traps.// 13 maxcount: max amount of skill instances to place on the ground when // player_land_skill_limit/monster_land_skill_limit is enabled. For skills // that attack using a path, this is the path length to be used.
-
Help me please. Just the dropping of all skulls from inventory.
-
6 hours ago, Alayne said:those variables means "start an event at 5, start an event at 6. If 0, then doesn't start, if 1 then start"
Got it! thnx!
-
On 12/4/2016 at 4:47 AM, Omnipotent said:Updated to v1.1:
Using constants in slots.
Fix cards and refine checking on evo.
Fix exp evo mode
Hi Omnipotent,
Is this still working? I tried the script i went on 1000% from evolving still no evolving happened.
Warper NPC for Pre-Re (Bug)
in Script Support
Posted
I'm using the same script in Hercules trunk.
Here: