Ver código fonte

- Second Part of BattleGround Implementation.
* Still need to merge visual studio files and scripts.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13551 54d463be-8e91-2dee-dedb-b68131a5f0ec

zephyrus 16 anos atrás
pai
commit
2511a7069f

+ 61 - 0
conf/battle/battleground.conf

@@ -0,0 +1,61 @@
+//      ______  __    __                                 
+//     /\  _  \/\ \__/\ \                                
+//   __\ \ \L\ \ \ ,_\ \ \___      __    ___      __     
+// /'__`\ \  __ \ \ \/\ \  _ `\  /'__`\/' _ `\  /'__`\   
+///\  __/\ \ \/\ \ \ \_\ \ \ \ \/\  __//\ \/\ \/\ \L\.\_ 
+//\ \____\\ \_\ \_\ \__\\ \_\ \_\ \____\ \_\ \_\ \__/.\_\
+// \/____/ \/_/\/_/\/__/ \/_/\/_/\/____/\/_/\/_/\/__/\/_/
+//  _   _   _   _   _   _   _     _   _   _   _   _   _
+// / \ / \ / \ / \ / \ / \ / \   / \ / \ / \ / \ / \ / \ 
+//( e | n | g | l | i | s | h ) ( A | t | h | e | n | a )
+// \_/ \_/ \_/ \_/ \_/ \_/ \_/   \_/ \_/ \_/ \_/ \_/ \_/
+//
+//--------------------------------------------------------------
+// eAthena Battle Configuration File
+// Originally Translated by Peter Kieser <pfak@telus.net>
+// Made in to plainer English by Ancyker
+//--------------------------------------------------------------
+// Note 1: Value is a config switch (on/off, yes/no or 1/0)
+// Note 2: Value is in percents (100 means 100%)
+// Note 3: Value is a bit field. If no description is given,
+//         assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun)
+//--------------------------------------------------------------
+
+// Melee damage adjustments (non skills) for Battleground maps (Note 2)
+bg_short_attack_damage_rate: 80
+
+// Ranged damage adjustments (non skills) for Battleground maps (Note 2)
+bg_long_attack_damage_rate: 80
+
+// Weapon skills damage adjustments for Battleground maps (Note 2)
+bg_weapon_attack_damage_rate: 60
+
+// Magic skills damage adjustments for Battleground maps (Note 2)
+bg_magic_attack_damage_rate: 60
+
+// Misc skills damage adjustments for Battleground maps (Note 2)
+bg_misc_attack_damage_rate: 60
+
+// Flee penalty on BG grounds.
+// NOTE: It's %, not absolute, so 20 is -20% of your total flee
+bg_flee_penalty: 20
+
+// Interval before updating the bg-member map mini-dots (milliseconds)
+bg_update_interval: 1000
+
+// Reserved Guild ID's for battlegrounds
+// Please take care of this configuration, you need to take 2 guild ids manually created
+// in your guild database (txt or sql). Only the ID's are required.
+// Take care this this "Fake guilds" will be never used by players.
+bg_guild_id1: 998
+bg_guild_id2: 999
+
+// ** BattleGround Emblems **
+// In the folder /db you will find 2 files: 
+// bgemblem_1.ebm (used for General Guillaume Marollo)
+// bgemblem_2.ebm (used for Prince Croix Marollo)
+// You can set your own emblems for battleground, using files from the _tmpEmblem folder
+// in your client files, just remember to keep the names.
+
+// If player is idle for N seconds it will be announced to all battle members in the same team.
+bg_idle_announce: 30

+ 3 - 0
conf/battle_athena.conf

@@ -35,6 +35,9 @@ import: conf/battle/gm.conf
 //Guild and WoE settings
 import: conf/battle/guild.conf
 
+//Battleground settings
+import: conf/battle/battleground.conf
+
 //Item/card-specific and crafting related options.
 import: conf/battle/items.conf
 

+ 2 - 0
db/bgemblem_1.ebm

@@ -0,0 +1,2 @@
+xśí‘ÝoSeÇ?}[ß¶ť­Ývş1úvX»nt´]OéeÝ誝°BĆ`PŰ` ,ŃůÂôZCôĘŻáŤóB/Ś11b‚FCô’Ä$rĄ‰ÁxSĽśçéYşřđ9yžßs>Ď÷9ĎÉóŚM­5Ń e†~­z¶š[ĂçŤŕręM“ĽˇÇŮÔž	˛ąąIĘŕäţ®
+M.ţ"ÁUzéÄĚ=˘ÔGůÔłŹŰ#K”ĺm�¸«pKŰím%Ď ¶Ď¬·„Hµí žZć»ÎQîĘă<˛¤y�¨ń}D"~Ď®`ÇHŮä“ä,\ýH¦&>ę›äťž4ýÓüRX%Ô܉l±óu«Ęőös¸ąĄVąçL“6KŘMęC§ą:P仩»&;\¬s,Z{ąÖ%@Źć-«ÂÇţ'Ľqę#—ąé+Ňn±±*qÉ«ňCá"?†S´¸ůŢ1LŢíç7bř­-|›eĆą“´ŐM˝gŠz˙ËÚɬöónĽÂMÂ|Ů˝źĺ+¨N{Z=ü­ň«wЏEbĂć=S�ËÔkěŐ2N§“ŁŤ?,*sů‰ľő—¸aŕoŰ÷bŢ`Î,ł`”9ä‰p„v>ďÎňsn‰÷Pq°"G‰Űş	Řl|Ő‘cĂĄr;q’»m#LĐĘsŚ7!ľđŽS˛v1­ťůSž"0ŐmTM˙á±×—V«>Q¤'ĽH�OŻOz-gb«lËÓč^l˙ŻĽÖ7ţI˙¤čžßÉăÍúEÄb#±F<vt:/|@™	·ĺó]‰VEŁT<néţäŘQU)óŠÎůS§RÂ{Gź™QźYScş÷źu	/_Ęç_ß!˫ݗȻ„_P”Úľx<~¬Ż¶µŕظđAźO˝ňśĆţ’îkᏗíĄ#ÎĐěěł>I§ąYřAĎńšgŞłüâK}b˝{IřäË)ťśđ
$÷č~oň5áĎ.KRÓĐÁ•ĹśÝŢđ™ĹłÂŻ�ń‰žÓŻjź†Y’ć„ĺ‚[Ú=™ÍfĎővd¤ŚíśQş,ĽcřPCkLÎWć­VkĄbŞn»ô­«˙?ţźÉ	

BIN
db/bgemblem_2.ebm


+ 362 - 0
src/map/battleground.c

@@ -0,0 +1,362 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/timer.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+
+#include "battleground.h"
+#include "battle.h"
+#include "clif.h"
+#include "map.h"
+#include "npc.h"
+#include "pc.h"
+#include "pet.h"
+#include "homunculus.h"
+#include "mercenary.h"
+
+#include <string.h>
+#include <stdio.h>
+
+static DBMap* bg_team_db; // int bg_id -> struct battleground_data*
+static unsigned int bg_team_counter = 0; // Next bg_id
+struct guild bg_guild[2]; // Temporal fake guild information
+
+struct battleground_data* bg_team_search(int bg_id)
+{ // Search a BG Team using bg_id
+	if( !bg_id ) return NULL;
+	return (struct battleground_data *)idb_get(bg_team_db, bg_id);
+}
+
+struct map_session_data* bg_getavailablesd(struct battleground_data *bg)
+{
+	int i;
+	nullpo_retr(NULL, bg);
+	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL);
+	return( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL;
+}
+
+int bg_team_delete(int bg_id)
+{ // Deletes BG Team from db
+	int i;
+	struct map_session_data *sd;
+	struct battleground_data *bg = bg_team_search(bg_id);
+	struct guild *g;
+
+	if( bg == NULL ) return 0;
+	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+	{
+		if( (sd = bg->members[i].sd) == NULL )
+			continue;
+
+		bg_send_dot_remove(sd);
+		sd->state.bg_id = 0;
+		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
+			clif_bg_leave_single(sd, sd->status.name, "Leaving Battleground...");
+
+		clif_charnameupdate(sd);
+		clif_guild_emblem_area(&sd->bl);
+	}
+	idb_remove(bg_team_db, bg_id);
+	return 1;
+}
+
+int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y)
+{ // Warps a Team
+	int i;
+	struct battleground_data *bg = bg_team_search(bg_id);
+	if( bg == NULL ) return 0;
+	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+		if( bg->members[i].sd != NULL ) pc_setpos(bg->members[i].sd, mapindex, x, y, 3);
+	return 1;
+}
+
+int bg_send_dot_remove(struct map_session_data *sd)
+{
+	if( sd && sd->state.bg_id )
+		clif_bg_xy_remove(sd);
+	return 0;
+}
+
+int bg_team_join(int bg_id, struct map_session_data *sd)
+{ // Player joins team
+	int i;
+	struct battleground_data *bg = bg_team_search(bg_id);
+	struct map_session_data *pl_sd;
+
+	if( bg == NULL || sd == NULL || sd->state.bg_id ) return 0;
+
+	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL);
+	if( i == MAX_BG_MEMBERS ) return 0; // No free slots
+
+	sd->state.bg_id = bg_id;
+	bg->members[i].sd = sd;
+	bg->members[i].x = sd->bl.x;
+	bg->members[i].y = sd->bl.y;
+	bg->count++;
+
+	guild_send_dot_remove(sd);
+	clif_bg_belonginfo(sd);
+	// clif_bg_emblem(sd, bg->g);
+	clif_charnameupdate(sd);
+
+	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+	{
+		if( (pl_sd = bg->members[i].sd) == NULL )
+			continue;
+		clif_guild_basicinfo(pl_sd);
+		clif_bg_emblem(pl_sd, bg->g);
+		clif_bg_memberlist(pl_sd);
+		if( pl_sd != sd )
+			clif_hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp);
+	}
+
+	clif_guild_emblem_area(&sd->bl);
+	clif_bg_hp(sd);
+	clif_bg_xy(sd);
+
+	return 1;
+}
+
+int bg_team_leave(struct map_session_data *sd, int flag)
+{ // Single Player leaves team
+	int i, bg_id;
+	struct battleground_data *bg;
+	struct map_session_data *pl_sd;
+	struct guild *g;
+
+	if( sd == NULL || !sd->state.bg_id )
+		return 0;
+
+	// Packets
+	clif_bg_leave_single(sd, sd->status.name, "Leaving Battle...");
+	bg_send_dot_remove(sd);
+	bg_id = sd->state.bg_id;
+	sd->state.bg_id = 0;
+
+	if( sd->status.guild_id && (g = guild_search(sd->status.guild_id)) != NULL )
+	{ // Refresh Guild Information
+		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);
+	}
+
+	clif_charnameupdate(sd);
+	clif_guild_emblem_area(&sd->bl);
+
+	if( (bg = bg_team_search(bg_id)) == NULL )
+		return 0;
+
+	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd);
+	if( i < MAX_BG_MEMBERS ) // Removes member from BG
+		memset(&bg->members[i], 0, sizeof(bg->members[0]));
+
+	bg->count--;
+	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+	{ // Update other BG members
+		if( (pl_sd = bg->members[i].sd) == NULL )
+			continue;
+		if( flag )
+			clif_bg_expulsion_single(pl_sd, sd->status.name, "User has quit the game...");
+		else
+			clif_bg_leave_single(pl_sd, sd->status.name, "Leaving Battle...");
+
+		clif_guild_basicinfo(pl_sd);
+		clif_bg_emblem(pl_sd, bg->g);
+		clif_bg_memberlist(pl_sd);
+	}
+
+	if( bg->logout_event[0] && flag )
+		npc_event(sd, bg->logout_event, 0);
+
+	return bg->count;
+}
+
+int bg_member_respawn(struct map_session_data *sd)
+{ // Respawn after killed
+	struct battleground_data *bg;
+	if( sd == NULL || !pc_isdead(sd) || !sd->state.bg_id || (bg = bg_team_search(sd->state.bg_id)) == NULL )
+		return 0;
+	if( bg->mapindex == 0 )
+		return 0; // Respawn not handled by Core
+	pc_setpos(sd, bg->mapindex, bg->x, bg->y, 0);
+	status_revive(&sd->bl, 1, 100);
+
+	return 1; // Warped
+}
+
+struct guild* bg_guild_get(int bg_id)
+{ // Return Fake Guild for BG Members
+	struct battleground_data *bg = bg_team_search(bg_id);
+	if( bg == NULL ) return NULL;
+	return bg->g;
+}
+
+int bg_create(unsigned short mapindex, short rx, short ry, int guild_index, const char *ev, const char *dev)
+{
+	struct battleground_data *bg;
+	bg_team_counter++;
+
+	CREATE(bg, struct battleground_data, 1);
+	bg->bg_id = bg_team_counter;
+	bg->count = 0;
+	bg->g = &bg_guild[guild_index];
+	bg->mapindex = mapindex;
+	bg->x = rx;
+	bg->y = ry;
+	safestrncpy(bg->logout_event, ev, sizeof(bg->logout_event));
+	safestrncpy(bg->die_event, dev, sizeof(bg->die_event));
+
+	memset(&bg->members, 0, sizeof(bg->members));
+	idb_put(bg_team_db, bg_team_counter, bg);
+
+	return bg->bg_id;
+}
+
+int bg_team_get_id(struct block_list *bl)
+{
+	nullpo_retr(0, bl);
+	switch( bl->type )
+	{
+		case BL_PC:
+			return ((TBL_PC*)bl)->state.bg_id;
+		case BL_PET:
+			if( ((TBL_PET*)bl)->msd )
+				return ((TBL_PET*)bl)->msd->state.bg_id;
+			break;
+		case BL_MOB:
+		{
+			struct map_session_data *msd;
+			struct mob_data *md = (TBL_MOB*)bl;
+			if( md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL )
+				return msd->state.bg_id;
+			return md->state.bg_id;
+		}
+		case BL_HOM:
+			if( ((TBL_HOM*)bl)->master )
+				return ((TBL_HOM*)bl)->master->state.bg_id;
+			break;
+		case BL_MER:
+			if( ((TBL_MER*)bl)->master )
+				return ((TBL_MER*)bl)->master->state.bg_id;
+			break;
+		case BL_SKILL:
+			return ((TBL_SKILL*)bl)->group->bg_id;
+	}
+
+	return 0;
+}
+
+int bg_send_message(struct map_session_data *sd, const char *mes, int len)
+{
+	struct battleground_data *bg;
+
+	nullpo_retr(0, sd);
+	if( sd->state.bg_id == 0 || (bg = bg_team_search(sd->state.bg_id)) == NULL )
+		return 0;
+	clif_bg_message(bg, sd->status.account_id, mes, len);
+	return 0;
+}
+
+int bg_send_xy_timer_sub(DBKey key, void *data, va_list ap)
+{
+	struct battleground_data *bg = (struct battleground_data *)data;
+	struct map_session_data *sd;
+	int i;
+	nullpo_retr(0, bg);
+	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+	{
+		if( (sd = bg->members[i].sd) == NULL )
+			continue;
+		if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y )
+		{ // xy update
+			bg->members[i].x = sd->bl.x;
+			bg->members[i].y = sd->bl.y;
+			clif_bg_xy(sd);
+		}
+		if( battle_config.bg_idle_announce && !bg->members[i].afk && DIFF_TICK(last_tick, sd->idletime) >= battle_config.bg_idle_announce && bg->g )
+		{ // Idle announces
+			char output[128];
+			bg->members[i].afk = 1;
+			sprintf(output, "%s : %s seens to be away...", bg->g->name, sd->status.name);
+
+			clif_bg_message(bg, 0, output, strlen(output));
+		}
+	}
+	return 0;
+}
+
+int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr data)
+{
+	bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
+	return 0;
+}
+
+void bg_guild_build_data(void)
+{
+	int i, j;
+	memset(&bg_guild, 0, sizeof(bg_guild));
+	for( i = 1; i <= 2; i++ )
+	{ // Emblem Data
+		FILE* fp = NULL;
+		char path[256];
+
+		j = i - 1;
+		sprintf(path, "%s/bgemblem_%d.ebm", db_path, i);
+		if( (fp = fopen(path, "rb")) == NULL )
+			continue;
+
+		bg_guild[j].emblem_id = 1;
+		fseek(fp, 0, SEEK_END);
+		bg_guild[j].emblem_len = ftell(fp);
+		fseek(fp, 0, SEEK_SET);
+		fread(&bg_guild[j].emblem_data, 1, bg_guild[j].emblem_len, fp);
+		fclose(fp);
+
+		ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"' emblem data file.\n", path);
+	}
+
+	// Guild Data - Guillaume
+	strncpy(bg_guild[0].name, "Blue Team", NAME_LENGTH);
+	strncpy(bg_guild[0].master, "General Guillaume Marollo", NAME_LENGTH);
+	bg_guild[0].guild_id = battle_config.bg_guild_id1;
+	bg_guild[0].guild_lv = 1;
+	strncpy(bg_guild[0].position[0].name, "Blue Team", NAME_LENGTH);
+	bg_guild[0].max_member = MAX_BG_MEMBERS;
+
+	// Guild Data - Croix
+	strncpy(bg_guild[1].name, "Red Team", NAME_LENGTH);
+	strncpy(bg_guild[1].master, "Prince Croix Marollo", NAME_LENGTH);
+	bg_guild[1].guild_id = battle_config.bg_guild_id2;
+	bg_guild[1].guild_lv = 1;
+	strncpy(bg_guild[1].position[0].name, "Red Team", NAME_LENGTH);
+	bg_guild[1].max_member = MAX_BG_MEMBERS;
+}
+
+void do_init_battleground(void)
+{
+	bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA);
+	add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer");
+	add_timer_interval(gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval);
+	bg_guild_build_data();
+}
+
+void do_final_battleground(void)
+{
+	bg_team_db->destroy(bg_team_db, NULL);
+}

+ 50 - 0
src/map/battleground.h

@@ -0,0 +1,50 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _BATTLEGROUND_H_
+#define _BATTLEGROUND_H_
+
+#include "../common/mmo.h" // struct party
+#include "guild.h"
+
+#define MAX_BG_MEMBERS 30
+
+struct battleground_member_data {
+	unsigned short x, y;
+	struct map_session_data *sd;
+	unsigned afk : 1;
+};
+
+struct battleground_data {
+	unsigned int bg_id;
+	unsigned char count;
+	struct battleground_member_data members[MAX_BG_MEMBERS];
+	// Fake Guild Link
+	struct guild *g;
+	// BG Cementery
+	unsigned short mapindex, x, y;
+	// Logout Event
+	char logout_event[50];
+	char die_event[50];
+};
+
+extern struct guild bg_guild[];
+
+void do_init_battleground(void);
+void do_final_battleground(void);
+
+struct battleground_data* bg_team_search(int bg_id);
+struct guild* bg_guild_get(int bg_id);
+int bg_send_dot_remove(struct map_session_data *sd);
+int bg_team_get_id(struct block_list *bl);
+struct map_session_data* bg_getavailablesd(struct battleground_data *bg);
+
+int bg_create(unsigned short mapindex, short rx, short ry, int guild_index, const char *ev, const char *dev);
+int bg_team_join(int bg_id, struct map_session_data *sd);
+int bg_team_delete(int bg_id);
+int bg_team_leave(struct map_session_data *sd, int flag);
+int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
+int bg_member_respawn(struct map_session_data *sd);
+int bg_send_message(struct map_session_data *sd, const char *mes, int len);
+
+#endif /* _BATTLEGROUND_H_ */