- Commiting a bunch of cleanups piled up from the past few weeks/months/years.
- Updated unitwarp so that an id of "0" causes the script's rid to be warped. - Updated the Brasilis ontouchNPC warp command to use unitwarp instead. - Signum Crucis's duration is now specified in the skill_cast_db file - Updated @warp/@jump commands so that when an invalid tile is specified, a nearby cell is chosen (rather than using a map-wide random value) - The if(req.weapon) code was broken, since req.weapon is never "0" for a skill. Updated the code so that the requirement of '99' (any weapon) is stored as 0, in order to make the checks effective. - Cleaned up the code for script command warpparty - Fixed the define itemdb_canrefine() - Cleaned up some the status_damage() function - Fixed map_random_dir(), which at times would pick cells that didn't preserve the required distance. - Some aesthetic code cleanups. - Fixed some possible crashes for skills where the code assumes the caster is a player. - Fixed a bunch of idiotic code-snippets that should have embarrassed whoever was responsible for them. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14929 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
ebfc42b8d5
commit
b7ad7aa055
@ -1,5 +1,8 @@
|
||||
Date Added
|
||||
|
||||
2011/08/10
|
||||
* Updated unitwarp so that an id of "0" causes the script's rid to be warped. This allows OnTouchNPC scripts to warp the monster. [Skotlex]
|
||||
* Updated @warp/@jump commands so that when an invalid tile is specified, a nearby cell is chosen.
|
||||
2011/08/06
|
||||
* Added missing fields to guild belong info packet 0x16c (ZC_UPDATE_GDID). [Ai4rei]
|
||||
2011/07/31
|
||||
|
@ -88,7 +88,7 @@
|
||||
//-- AL_HOLYWATER
|
||||
31,1000,500,0,0,0
|
||||
//-- AL_CRUCIS
|
||||
32,500,2000,0,0,0
|
||||
32,500,2000,0,60000,0
|
||||
//-- AL ANGELUS
|
||||
33,500,3500,0,30000:60000:90000:120000:150000:180000:210000:240000:270000:300000,0
|
||||
//-- AL_BLESSING
|
||||
|
@ -181,6 +181,8 @@
|
||||
//= Documented special map names recognized by 'warpguild'. [Ai4rei]
|
||||
//= 3.45.20110709
|
||||
//= Added 'getmercinfo' command. [Ai4rei]
|
||||
//= 3.46.20110810
|
||||
//= Added information on OnTouchNPC and 'unitwarp' special case [Skotlex]
|
||||
//=========================================================
|
||||
|
||||
This document is a reference manual for all the scripting commands and functions
|
||||
@ -423,7 +425,8 @@ spanning triggerX cells in every direction across X and triggerY in every
|
||||
direction across Y. Walking into that area will trigger the NPC. If no
|
||||
'OnTouch:' special label is present in the NPC code, the execution will start
|
||||
from the beginning of the script, otherwise, it will start from the 'OnTouch:'
|
||||
label.
|
||||
label. Monsters can also trigger the NPC, though the label 'OnTouchNPC:' is
|
||||
used in this case.
|
||||
|
||||
The code part is the script code that will execute whenever the NPC is
|
||||
triggered. It may contain commands and function calls, descriptions of which
|
||||
@ -5241,6 +5244,10 @@ Example(s):
|
||||
|
||||
Okay, these commands should be fairly self explaining.
|
||||
For the emotions, you can look in db/const.txt for prefixes with e_
|
||||
PS: unitwarp supports a <GID> of zero, which causes the executor of the script to be affected. This can be used with OnTouchNPC to warp monsters:
|
||||
|
||||
OnTouchNPC:
|
||||
unitwarp 0,"this",-1,-1;
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
Date Added
|
||||
======
|
||||
2011/08/10
|
||||
* Updated the quests_brasilis ontouchNPC warp command to use unitwarp instead. [Skotlex]
|
||||
2011/08/09
|
||||
* Rev. 14928 Implemented the rest of Brasilis, and updated existing Brasilis NPCs. [L0ne_W0lf]
|
||||
2011/07/16
|
||||
|
@ -2669,7 +2669,7 @@ bra_dun02,67,205,5 script Recluse#bra 475,3,3,{
|
||||
end;
|
||||
|
||||
OnTouchNPC:
|
||||
warp "bra_dun02",67,215;
|
||||
unitwarp 0,"this",67,215;
|
||||
end;
|
||||
}
|
||||
|
||||
|
@ -416,7 +416,7 @@ ACMD_FUNC(mapmove)
|
||||
{
|
||||
char map_name[MAP_NAME_LENGTH_EXT];
|
||||
unsigned short mapindex;
|
||||
int x = 0, y = 0;
|
||||
short x = 0, y = 0;
|
||||
int m = -1;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
@ -424,8 +424,8 @@ ACMD_FUNC(mapmove)
|
||||
memset(map_name, '\0', sizeof(map_name));
|
||||
|
||||
if (!message || !*message ||
|
||||
(sscanf(message, "%15s %d %d", map_name, &x, &y) < 3 &&
|
||||
sscanf(message, "%15[^,],%d,%d", map_name, &x, &y) < 1)) {
|
||||
(sscanf(message, "%15s %hd %hd", map_name, &x, &y) < 3 &&
|
||||
sscanf(message, "%15[^,],%hd,%hd", map_name, &x, &y) < 1)) {
|
||||
|
||||
clif_displaymessage(fd, "Please, enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>).");
|
||||
return -1;
|
||||
@ -443,7 +443,8 @@ ACMD_FUNC(mapmove)
|
||||
if ((x || y) && map_getcell(m, x, y, CELL_CHKNOPASS))
|
||||
{ //This is to prevent the pc_setpos call from printing an error.
|
||||
clif_displaymessage(fd, msg_txt(2));
|
||||
x = y = 0; //Invalid cell, use random spot.
|
||||
if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1))
|
||||
x = y = 0; //Invalid cell, use random spot.
|
||||
}
|
||||
if (map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
|
||||
clif_displaymessage(fd, msg_txt(247));
|
||||
@ -548,13 +549,13 @@ ACMD_FUNC(jumpto)
|
||||
*------------------------------------------*/
|
||||
ACMD_FUNC(jump)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
short x = 0, y = 0;
|
||||
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
memset(atcmd_output, '\0', sizeof(atcmd_output));
|
||||
|
||||
sscanf(message, "%d %d", &x, &y);
|
||||
sscanf(message, "%hd %hd", &x, &y);
|
||||
|
||||
if (map[sd->bl.m].flag.noteleport && battle_config.any_warp_GM_min_level > pc_isGM(sd)) {
|
||||
clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map.
|
||||
@ -570,7 +571,8 @@ ACMD_FUNC(jump)
|
||||
if ((x || y) && map_getcell(sd->bl.m, x, y, CELL_CHKNOPASS))
|
||||
{ //This is to prevent the pc_setpos call from printing an error.
|
||||
clif_displaymessage(fd, msg_txt(2));
|
||||
x = y = 0; //Invalid cell, use random spot.
|
||||
if (!map_search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1))
|
||||
x = y = 0; //Invalid cell, use random spot.
|
||||
}
|
||||
|
||||
pc_setpos(sd, sd->mapindex, x, y, CLR_TELEPORT);
|
||||
|
@ -114,7 +114,7 @@ int itemdb_searchrandomid(int flags);
|
||||
|
||||
#define itemdb_value_buy(n) itemdb_search(n)->value_buy
|
||||
#define itemdb_value_sell(n) itemdb_search(n)->value_sell
|
||||
#define itemdb_canrefine(n) itemdb_search(n)->flag.no_refine
|
||||
#define itemdb_canrefine(n) (!itemdb_search(n)->flag.no_refine)
|
||||
//Item trade restrictions [Skotlex]
|
||||
int itemdb_isdropable_sub(struct item_data *, int, int);
|
||||
int itemdb_cantrade_sub(struct item_data*, int, int);
|
||||
|
@ -2305,7 +2305,7 @@ int map_random_dir(struct block_list *bl, short *x, short *y)
|
||||
if (dist < 1) dist =1;
|
||||
|
||||
do {
|
||||
j = rand()%8; //Pick a random direction
|
||||
j = 1 + 2*(rand()%4); //Pick a random diagonal direction
|
||||
segment = 1+(rand()%dist); //Pick a random interval from the whole vector in that direction
|
||||
xi = bl->x + segment*dirx[j];
|
||||
segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
|
||||
|
@ -7168,7 +7168,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
|
||||
pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
|
||||
|
||||
if(battle_config.battle_log)
|
||||
ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id->equip,req_pos);
|
||||
ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
|
||||
if(!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
|
||||
clif_equipitemack(sd,n,0,0); // fail
|
||||
return 0;
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "buyingstore.h" // struct s_buyingstore
|
||||
#include "itemdb.h" // MAX_ITEMGROUP
|
||||
#include "map.h" // RC_MAX
|
||||
#include "pc.h" // struct map_session_data
|
||||
#include "script.h" // struct script_reg, struct script_regstr
|
||||
#include "searchstore.h" // struct s_search_store_info
|
||||
#include "status.h" // OPTION_*, struct weapon_atk
|
||||
|
@ -4559,7 +4559,7 @@ BUILDIN_FUNC(warpparty)
|
||||
struct party_data* p;
|
||||
int type;
|
||||
int mapindex;
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
const char* str = script_getstr(st,2);
|
||||
int x = script_getnum(st,3);
|
||||
@ -4579,9 +4579,27 @@ BUILDIN_FUNC(warpparty)
|
||||
: ( strcmp(str,"Leader")==0 ) ? 3
|
||||
: 4;
|
||||
|
||||
if( type == 2 && ( sd = script_rid2sd(st) ) == NULL )
|
||||
{// "SavePoint" uses save point of the currently attached player
|
||||
return 0;
|
||||
switch (type)
|
||||
{
|
||||
case 3:
|
||||
for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++);
|
||||
if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online
|
||||
return 0;
|
||||
pl_sd = p->data[i].sd;
|
||||
mapindex = pl_sd->mapindex;
|
||||
x = pl_sd->bl.x;
|
||||
y = pl_sd->bl.y;
|
||||
break;
|
||||
case 4:
|
||||
mapindex = mapindex_name2id(str);
|
||||
break;
|
||||
case 2:
|
||||
//"SavePoint" uses save point of the currently attached player
|
||||
if (( sd = script_rid2sd(st) ) == NULL )
|
||||
return 0;
|
||||
default:
|
||||
mapindex = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PARTY; i++)
|
||||
@ -4610,25 +4628,9 @@ BUILDIN_FUNC(warpparty)
|
||||
pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
|
||||
break;
|
||||
case 3: // Leader
|
||||
for(j = 0; j < MAX_PARTY && !p->party.member[j].leader; j++);
|
||||
if (j == MAX_PARTY || !p->data[j].sd) //Leader not found / not online
|
||||
return 0;
|
||||
mapindex = p->data[j].sd->mapindex;
|
||||
x = p->data[j].sd->bl.x;
|
||||
y = p->data[j].sd->bl.y;
|
||||
for (j = 0; j < MAX_PARTY; j++)
|
||||
{
|
||||
pl_sd = p->data[j].sd;
|
||||
if (!pl_sd)
|
||||
continue;
|
||||
if(map[pl_sd->bl.m].flag.noreturn || map[pl_sd->bl.m].flag.nowarp)
|
||||
continue;
|
||||
pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
|
||||
}
|
||||
break;
|
||||
case 4: // m,x,y
|
||||
if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp)
|
||||
pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT);
|
||||
pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -6574,6 +6576,9 @@ BUILDIN_FUNC(strnpcinfo)
|
||||
case 3: // unique name
|
||||
name = aStrdup(nd->exname);
|
||||
break;
|
||||
case 4: // map name
|
||||
name = aStrdup(map[nd->bl.m].name);
|
||||
break;
|
||||
}
|
||||
|
||||
if(name)
|
||||
@ -13452,8 +13457,11 @@ BUILDIN_FUNC(unitwarp)
|
||||
map = map_mapname2mapid(script_getstr(st, 3));
|
||||
x = (short)script_getnum(st,4);
|
||||
y = (short)script_getnum(st,5);
|
||||
|
||||
bl = map_id2bl(unit_id);
|
||||
|
||||
if (!unit_id) //Warp the script's runner
|
||||
bl = map_id2bl(st->rid);
|
||||
else
|
||||
bl = map_id2bl(unit_id);
|
||||
if( map >= 0 && bl != NULL )
|
||||
script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT));
|
||||
else
|
||||
|
@ -268,8 +268,8 @@ int skill_get_range2 (struct block_list *bl, int id, int lv)
|
||||
int skill_calc_heal(struct block_list *src, struct block_list *target, int skill_id, int skill_lv, bool heal)
|
||||
{
|
||||
int skill, hp;
|
||||
struct map_session_data *sd = map_id2sd(src->id);
|
||||
struct map_session_data *tsd = map_id2sd(target->id);
|
||||
struct map_session_data *sd = BL_CAST(BL_PC, src);
|
||||
struct map_session_data *tsd = BL_CAST(BL_PC, target);
|
||||
struct status_change* sc;
|
||||
|
||||
switch( skill_id )
|
||||
@ -1008,8 +1008,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
|
||||
|
||||
tbl = (sd->autospell[i].id < 0) ? src : bl;
|
||||
|
||||
if( !battle_check_range(src, tbl, skill_get_range2(src, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
|
||||
continue; // If autospell_check_range is yes, fail the autocast.
|
||||
if( battle_config.autospell_check_range &&
|
||||
!battle_check_range(src, tbl, skill_get_range2(src, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) )
|
||||
continue;
|
||||
|
||||
if (skill == AS_SONICBLOW)
|
||||
pc_stop_attack(sd); //Special case, Sonic Blow autospell should stop the player attacking.
|
||||
@ -1113,7 +1114,8 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, int s
|
||||
continue;
|
||||
tbl = (sd->autospell3[i].id < 0) ? &sd->bl : bl;
|
||||
|
||||
if( !battle_check_range(&sd->bl, tbl, skill_get_range2(&sd->bl, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
|
||||
if( battle_config.autospell_check_range &&
|
||||
!battle_check_range(&sd->bl, tbl, skill_get_range2(&sd->bl, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) )
|
||||
continue;
|
||||
|
||||
sd->state.autocast = 1;
|
||||
@ -1640,13 +1642,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
|
||||
|
||||
//Spirit of Wizard blocks Kaite's reflection
|
||||
if( type == 2 && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD )
|
||||
{ //Consume one Fragment per hit of the casted skill. Val3 is the skill id and val4 is the ID of the damage src.
|
||||
//This should account for ground spells (and single target spells will be completed on castend_id) [Skotlex]
|
||||
type = pc_search_inventory (tsd, 7321);
|
||||
if (type >= 0)
|
||||
pc_delitem(tsd, type, 1, 0, 1);
|
||||
|
||||
{ //Consume one Fragment per hit of the casted skill? [Skotlex]
|
||||
type = tsd?pc_search_inventory (tsd, 7321):0;
|
||||
if (type >= 0) {
|
||||
if ( tsd ) pc_delitem(tsd, type, 1, 0, 1);
|
||||
dmg.damage = dmg.damage2 = 0;
|
||||
dmg.dmg_lv = ATK_MISS;
|
||||
sc->data[SC_SPIRIT]->val3 = skillid;
|
||||
@ -3266,7 +3265,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
{
|
||||
int per = 0, sper = 0;
|
||||
if (status_get_sc(bl)->data[SC_HELLPOWER])
|
||||
if (tsc && tsc->data[SC_HELLPOWER])
|
||||
break;
|
||||
|
||||
if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0)
|
||||
@ -3310,7 +3309,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
|
||||
case AL_CRUCIS:
|
||||
if (flag&1)
|
||||
sc_start(bl,type, 23+skilllv*4 +status_get_lv(src) -status_get_lv(bl), skilllv,60000);
|
||||
sc_start(bl,type, 23+skilllv*4 +status_get_lv(src) -status_get_lv(bl), skilllv,skill_get_time(skillid,skilllv));
|
||||
else {
|
||||
map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR,
|
||||
src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
||||
@ -3395,7 +3394,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
heal = status_percent_heal(bl, 100, 0);
|
||||
clif_skill_nodamage(NULL, bl, AL_HEAL, heal, 1);
|
||||
if( skillid == NPC_ALLHEAL && dstmd )
|
||||
if( dstmd )
|
||||
{ // Reset Damage Logs
|
||||
memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog));
|
||||
dstmd->tdmg = 0;
|
||||
@ -3857,7 +3856,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
mer->devotion_flag = 1; // Mercenary Devoting Owner
|
||||
|
||||
clif_skill_nodamage(src, bl, skillid, skilllv,
|
||||
sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skillid,skilllv), skill_get_time2(skillid, skilllv), 1000));
|
||||
sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skillid,skilllv),0, skill_get_time2(skillid, skilllv)));
|
||||
clif_devotion(src, NULL);
|
||||
}
|
||||
break;
|
||||
@ -6194,7 +6193,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
|
||||
case SA_VIOLENTGALE:
|
||||
{ //Does not consumes if the skill is already active. [Skotlex]
|
||||
struct skill_unit_group *sg;
|
||||
if ((sg= skill_locate_element_field(&sd->bl)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE ))
|
||||
if ((sg= skill_locate_element_field(src)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE ))
|
||||
{
|
||||
if (sg->limit - DIFF_TICK(gettick(), sg->tick) > 0)
|
||||
{
|
||||
@ -8200,7 +8199,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
|
||||
require = skill_get_requirement(sd,skill,lv);
|
||||
|
||||
//Can only update state when weapon/arrow info is checked.
|
||||
if (require.weapon) sd->state.arrow_atk = require.ammo?1:0;
|
||||
sd->state.arrow_atk = require.ammo?1:0;
|
||||
|
||||
// perform skill-specific checks (and actions)
|
||||
switch( skill )
|
||||
@ -8834,9 +8833,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short
|
||||
|
||||
req.weapon = skill_db[j].weapon;
|
||||
|
||||
req.ammo = skill_db[j].ammo;
|
||||
req.ammo_qty = skill_db[j].ammo_qty[lv-1];
|
||||
if (req.weapon && !req.ammo && skill && skill_isammotype(sd, skill))
|
||||
if (req.ammo_qty)
|
||||
req.ammo = skill_db[j].ammo;
|
||||
|
||||
if (!req.ammo && skill && skill_isammotype(sd, skill))
|
||||
{ //Assume this skill is using the weapon, therefore it requires arrows.
|
||||
req.ammo = 0xFFFFFFFF; //Enable use on all ammo types.
|
||||
req.ammo_qty = 1;
|
||||
@ -11650,9 +11651,9 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
|
||||
for( j = 0; j < 32; j++ )
|
||||
{
|
||||
int l = atoi(p);
|
||||
if( l == 99 ) // magic value?
|
||||
if( l == 99 ) // Any weapon
|
||||
{
|
||||
skill_db[i].weapon = 0xffffffff;
|
||||
skill_db[i].weapon = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -11668,12 +11669,12 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
|
||||
for( j = 0; j < 32; j++ )
|
||||
{
|
||||
int l = atoi(p);
|
||||
if( l == 99 ) // magic value?
|
||||
if( l == 99 ) // Any ammo type
|
||||
{
|
||||
skill_db[i].ammo = 0xffffffff;
|
||||
skill_db[i].ammo = 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
else if( l ) // 0 not allowed?
|
||||
else if( l ) // 0 stands for no requirement
|
||||
skill_db[i].ammo |= 1<<l;
|
||||
p = strchr(p,':');
|
||||
if( !p )
|
||||
|
@ -656,7 +656,7 @@ int status_charge(struct block_list* bl, int hp, int sp)
|
||||
//If flag&1, damage is passive and does not triggers cancelling status changes.
|
||||
//If flag&2, fail if target does not has enough to substract.
|
||||
//If flag&4, if killed, mob must not give exp/loot.
|
||||
//If flag&8, sp loss on dead target.
|
||||
//flag will be set to &8 when damaging sp of a dead character
|
||||
int status_damage(struct block_list *src,struct block_list *target,int hp, int sp, int walkdelay, int flag)
|
||||
{
|
||||
struct status_data *status;
|
||||
@ -666,18 +666,15 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
sp = 0; //Not a valid SP target.
|
||||
|
||||
if (hp < 0) { //Assume absorbed damage.
|
||||
status_heal(target, cap_value(-hp, INT_MIN, INT_MAX), 0, 1);
|
||||
status_heal(target, -hp, 0, 1);
|
||||
hp = 0;
|
||||
}
|
||||
|
||||
if (sp < 0) {
|
||||
status_heal(target, 0, cap_value(-sp, INT_MIN, INT_MAX), 1);
|
||||
status_heal(target, 0, -sp, 1);
|
||||
sp = 0;
|
||||
}
|
||||
|
||||
if (!hp && !sp)
|
||||
return 0;
|
||||
|
||||
if (target->type == BL_SKILL)
|
||||
return skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick());
|
||||
|
||||
@ -685,6 +682,19 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
if( status == &dummy_status )
|
||||
return 0;
|
||||
|
||||
if ((unsigned int)hp >= status->hp) {
|
||||
if (flag&2) return 0;
|
||||
hp = status->hp;
|
||||
}
|
||||
|
||||
if ((unsigned int)sp > status->sp) {
|
||||
if (flag&2) return 0;
|
||||
sp = status->sp;
|
||||
}
|
||||
|
||||
if (!hp && !sp)
|
||||
return 0;
|
||||
|
||||
if( !status->hp )
|
||||
flag |= 8;
|
||||
|
||||
@ -694,10 +704,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
// return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp
|
||||
|
||||
sc = status_get_sc(target);
|
||||
if( battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
|
||||
if( hp && battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
|
||||
hp = 1;
|
||||
|
||||
if( hp && !(flag&(1|8)) ) {
|
||||
if( hp && !(flag&1) ) {
|
||||
if( sc ) {
|
||||
struct status_change_entry *sce;
|
||||
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
||||
@ -731,16 +741,6 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
unit_skillcastcancel(target, 2);
|
||||
}
|
||||
|
||||
if ((unsigned int)hp >= status->hp) {
|
||||
if (flag&2) return 0;
|
||||
hp = status->hp;
|
||||
}
|
||||
|
||||
if ((unsigned int)sp > status->sp) {
|
||||
if (flag&2) return 0;
|
||||
sp = status->sp;
|
||||
}
|
||||
|
||||
status->hp-= hp;
|
||||
status->sp-= sp;
|
||||
|
||||
@ -761,7 +761,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
case BL_MER: mercenary_damage((TBL_MER*)target,src,hp,sp); break;
|
||||
}
|
||||
|
||||
if( status->hp || flag&8 )
|
||||
if( status->hp || (flag&8) )
|
||||
{ //Still lives or has been dead before this damage.
|
||||
if (walkdelay)
|
||||
unit_set_walkdelay(target, gettick(), walkdelay, 0);
|
||||
@ -805,11 +805,11 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
||||
}
|
||||
}
|
||||
|
||||
if( !(flag&8) && sc && sc->data[SC_KAIZEL] )
|
||||
if( sc && sc->data[SC_KAIZEL] )
|
||||
{ //flag&8 = disable Kaizel
|
||||
int time = skill_get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1);
|
||||
//Look for Osiris Card's bonus effect on the character and revive 100% or revive normally
|
||||
if ( target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover == 1 )
|
||||
if ( target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover )
|
||||
status_revive(target, 100, 100);
|
||||
else
|
||||
status_revive(target, sc->data[SC_KAIZEL]->val2, 0);
|
||||
@ -869,7 +869,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
|
||||
sc = NULL;
|
||||
|
||||
if (hp < 0) {
|
||||
status_damage(NULL, bl, cap_value(-hp, INT_MIN, INT_MAX), 0, 0, 1);
|
||||
status_damage(NULL, bl, -hp, 0, 0, 1);
|
||||
hp = 0;
|
||||
}
|
||||
|
||||
@ -882,7 +882,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
|
||||
}
|
||||
|
||||
if(sp < 0) {
|
||||
status_damage(NULL, bl, 0, cap_value(-sp, INT_MIN, INT_MAX), 0, 1);
|
||||
status_damage(NULL, bl, 0, -sp, 0, 1);
|
||||
sp = 0;
|
||||
}
|
||||
|
||||
@ -1510,24 +1510,14 @@ int status_calc_mob_(struct mob_data* md, bool first)
|
||||
gc=guild_mapname2gc(map[md->bl.m].name);
|
||||
if (!gc)
|
||||
ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name);
|
||||
else {
|
||||
if(gc->castle_id > 23) {
|
||||
if(md->class_ == MOBID_EMPERIUM) {
|
||||
status->max_hp += 1000 * gc->defense;
|
||||
status->max_sp += 200 * gc->defense;
|
||||
status->hp = status->max_hp;
|
||||
status->sp = status->max_sp;
|
||||
status->def += (gc->defense+2)/3;
|
||||
status->mdef += (gc->defense+2)/3;
|
||||
}
|
||||
}else{
|
||||
status->max_hp += 1000 * gc->defense;
|
||||
status->max_sp += 200 * gc->defense;
|
||||
status->hp = status->max_hp;
|
||||
status->sp = status->max_sp;
|
||||
status->def += (gc->defense+2)/3;
|
||||
status->mdef += (gc->defense+2)/3;
|
||||
}
|
||||
else
|
||||
if(gc->castle_id < 24 || md->class_ == MOBID_EMPERIUM) {
|
||||
status->max_hp += 1000 * gc->defense;
|
||||
status->max_sp += 200 * gc->defense;
|
||||
status->hp = status->max_hp;
|
||||
status->sp = status->max_sp;
|
||||
status->def += (gc->defense+2)/3;
|
||||
status->mdef += (gc->defense+2)/3;
|
||||
}
|
||||
if(md->class_ != MOBID_EMPERIUM) {
|
||||
status->batk += status->batk * 10*md->guardian_data->guardup_lv/100;
|
||||
@ -2693,7 +2683,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|
||||
if (
|
||||
sc->data[SC_DANCING]
|
||||
|| (
|
||||
(((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
|
||||
(bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
|
||||
(sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)))
|
||||
)
|
||||
|| sc->data[SC_MAXIMIZEPOWER]
|
||||
@ -7250,15 +7240,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
}
|
||||
break;
|
||||
|
||||
case SC_DEVOTION:
|
||||
//FIXME: use normal status duration instead of a looping timer
|
||||
if( (sce->val4 -= 1000) > 0 )
|
||||
{
|
||||
sc_timer_next(1000+tick, status_change_timer, bl->id, data);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SC_BERSERK:
|
||||
// 5% every 10 seconds [DracoRPG]
|
||||
if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 )
|
||||
|
@ -8,6 +8,7 @@ struct block_list;
|
||||
struct mob_data;
|
||||
struct pet_data;
|
||||
struct homun_data;
|
||||
struct mercenary_data;
|
||||
struct status_change;
|
||||
|
||||
//Use this to refer the max refinery level [Skotlex]
|
||||
|
Loading…
x
Reference in New Issue
Block a user