1 | // Copyright (c) Athena Dev Teams - Licensed under GNU GPL |
---|
2 | // For more information, see LICENCE in the main folder |
---|
3 | |
---|
4 | #include "../common/cbasetypes.h" |
---|
5 | #include "../common/timer.h" |
---|
6 | #include "../common/nullpo.h" |
---|
7 | #include "../common/malloc.h" |
---|
8 | #include "../common/showmsg.h" |
---|
9 | #include "../common/ers.h" |
---|
10 | #include "../common/strlib.h" |
---|
11 | #include "../common/utils.h" |
---|
12 | |
---|
13 | #include "map.h" |
---|
14 | #include "path.h" |
---|
15 | #include "pc.h" |
---|
16 | #include "status.h" |
---|
17 | #include "skill.h" |
---|
18 | #include "mercenary.h" |
---|
19 | #include "mob.h" |
---|
20 | #include "itemdb.h" |
---|
21 | #include "clif.h" |
---|
22 | #include "pet.h" |
---|
23 | #include "guild.h" |
---|
24 | #include "party.h" |
---|
25 | #include "battle.h" |
---|
26 | |
---|
27 | #include <stdio.h> |
---|
28 | #include <stdlib.h> |
---|
29 | #include <string.h> |
---|
30 | #include <math.h> |
---|
31 | |
---|
32 | int attr_fix_table[4][ELE_MAX][ELE_MAX]; |
---|
33 | |
---|
34 | struct Battle_Config battle_config; |
---|
35 | static struct eri *delay_damage_ers; //For battle delay damage structures. |
---|
36 | |
---|
37 | int battle_getcurrentskill(struct block_list *bl) |
---|
38 | { //Returns the current/last skill in use by this bl. |
---|
39 | struct unit_data *ud; |
---|
40 | |
---|
41 | if (bl->type == BL_SKILL) { |
---|
42 | struct skill_unit * su = (struct skill_unit*)bl; |
---|
43 | return su->group?su->group->skill_id:0; |
---|
44 | } |
---|
45 | ud = unit_bl2ud(bl); |
---|
46 | return ud?ud->skillid:0; |
---|
47 | } |
---|
48 | |
---|
49 | /*========================================== |
---|
50 | * Get random targetting enemy |
---|
51 | *------------------------------------------*/ |
---|
52 | static int battle_gettargeted_sub(struct block_list *bl, va_list ap) |
---|
53 | { |
---|
54 | struct block_list **bl_list; |
---|
55 | struct unit_data *ud; |
---|
56 | int target_id; |
---|
57 | int *c; |
---|
58 | |
---|
59 | bl_list = va_arg(ap, struct block_list **); |
---|
60 | c = va_arg(ap, int *); |
---|
61 | target_id = va_arg(ap, int); |
---|
62 | |
---|
63 | if (bl->id == target_id) |
---|
64 | return 0; |
---|
65 | if (*c >= 24) |
---|
66 | return 0; |
---|
67 | |
---|
68 | ud = unit_bl2ud(bl); |
---|
69 | if (!ud) return 0; |
---|
70 | |
---|
71 | if (ud->target == target_id || ud->skilltarget == target_id) { |
---|
72 | bl_list[(*c)++] = bl; |
---|
73 | return 1; |
---|
74 | } |
---|
75 | return 0; |
---|
76 | } |
---|
77 | |
---|
78 | struct block_list* battle_gettargeted(struct block_list *target) |
---|
79 | { |
---|
80 | struct block_list *bl_list[24]; |
---|
81 | int c = 0; |
---|
82 | nullpo_retr(NULL, target); |
---|
83 | |
---|
84 | memset(bl_list, 0, sizeof(bl_list)); |
---|
85 | map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); |
---|
86 | if (c == 0 || c > 24) |
---|
87 | return NULL; |
---|
88 | return bl_list[rand()%c]; |
---|
89 | } |
---|
90 | |
---|
91 | |
---|
92 | //Returns the id of the current targetted character of the passed bl. [Skotlex] |
---|
93 | int battle_gettarget(struct block_list* bl) |
---|
94 | { |
---|
95 | switch (bl->type) |
---|
96 | { |
---|
97 | case BL_PC: return ((struct map_session_data*)bl)->ud.target; |
---|
98 | case BL_MOB: return ((struct mob_data*)bl)->target_id; |
---|
99 | case BL_PET: return ((struct pet_data*)bl)->target_id; |
---|
100 | case BL_HOM: return ((struct homun_data*)bl)->ud.target; |
---|
101 | } |
---|
102 | return 0; |
---|
103 | } |
---|
104 | |
---|
105 | static int battle_getenemy_sub(struct block_list *bl, va_list ap) |
---|
106 | { |
---|
107 | struct block_list **bl_list; |
---|
108 | struct block_list *target; |
---|
109 | int *c; |
---|
110 | |
---|
111 | bl_list = va_arg(ap, struct block_list **); |
---|
112 | c = va_arg(ap, int *); |
---|
113 | target = va_arg(ap, struct block_list *); |
---|
114 | |
---|
115 | if (bl->id == target->id) |
---|
116 | return 0; |
---|
117 | if (*c >= 24) |
---|
118 | return 0; |
---|
119 | if (status_isdead(bl)) |
---|
120 | return 0; |
---|
121 | if (battle_check_target(target, bl, BCT_ENEMY) > 0) { |
---|
122 | bl_list[(*c)++] = bl; |
---|
123 | return 1; |
---|
124 | } |
---|
125 | return 0; |
---|
126 | } |
---|
127 | |
---|
128 | // Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex] |
---|
129 | struct block_list* battle_getenemy(struct block_list *target, int type, int range) |
---|
130 | { |
---|
131 | struct block_list *bl_list[24]; |
---|
132 | int c = 0; |
---|
133 | memset(bl_list, 0, sizeof(bl_list)); |
---|
134 | map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target); |
---|
135 | if (c == 0 || c > 24) |
---|
136 | return NULL; |
---|
137 | return bl_list[rand()%c]; |
---|
138 | } |
---|
139 | |
---|
140 | // _E?[WÌx |
---|
141 | struct delay_damage { |
---|
142 | struct block_list *src; |
---|
143 | int target; |
---|
144 | int damage; |
---|
145 | int delay; |
---|
146 | unsigned short distance; |
---|
147 | unsigned short skill_lv; |
---|
148 | unsigned short skill_id; |
---|
149 | enum damage_lv dmg_lv; |
---|
150 | unsigned short attack_type; |
---|
151 | }; |
---|
152 | |
---|
153 | int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data) |
---|
154 | { |
---|
155 | struct delay_damage *dat = (struct delay_damage *)data; |
---|
156 | struct block_list *target = map_id2bl(dat->target); |
---|
157 | if (target && dat && map_id2bl(id) == dat->src && target->prev != NULL && !status_isdead(target) && |
---|
158 | target->m == dat->src->m && |
---|
159 | (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == -1) && |
---|
160 | check_distance_bl(dat->src, target, dat->distance)) //Check to see if you haven't teleported. [Skotlex] |
---|
161 | { |
---|
162 | map_freeblock_lock(); |
---|
163 | status_fix_damage(dat->src, target, dat->damage, dat->delay); |
---|
164 | if (dat->damage > 0 && dat->attack_type) |
---|
165 | { |
---|
166 | if (!status_isdead(target)) |
---|
167 | skill_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); |
---|
168 | skill_counter_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); |
---|
169 | } |
---|
170 | map_freeblock_unlock(); |
---|
171 | } |
---|
172 | ers_free(delay_damage_ers, dat); |
---|
173 | return 0; |
---|
174 | } |
---|
175 | |
---|
176 | int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay) |
---|
177 | { |
---|
178 | struct delay_damage *dat; |
---|
179 | nullpo_retr(0, src); |
---|
180 | nullpo_retr(0, target); |
---|
181 | |
---|
182 | if (!battle_config.delay_battle_damage) { |
---|
183 | map_freeblock_lock(); |
---|
184 | status_fix_damage(src, target, damage, ddelay); |
---|
185 | if (damage > 0 && attack_type) |
---|
186 | { |
---|
187 | if (!status_isdead(target)) |
---|
188 | skill_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); |
---|
189 | skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); |
---|
190 | } |
---|
191 | map_freeblock_unlock(); |
---|
192 | return 0; |
---|
193 | } |
---|
194 | dat = ers_alloc(delay_damage_ers, struct delay_damage); |
---|
195 | dat->src = src; |
---|
196 | dat->target = target->id; |
---|
197 | dat->skill_id = skill_id; |
---|
198 | dat->skill_lv = skill_lv; |
---|
199 | dat->attack_type = attack_type; |
---|
200 | dat->damage = damage; |
---|
201 | dat->dmg_lv = dmg_lv; |
---|
202 | dat->delay = ddelay; |
---|
203 | dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. |
---|
204 | if (src->type != BL_PC && amotion > 1000) |
---|
205 | amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] |
---|
206 | add_timer(tick+amotion, battle_delay_damage_sub, src->id, (int)dat); |
---|
207 | |
---|
208 | return 0; |
---|
209 | } |
---|
210 | |
---|
211 | int battle_attr_ratio(int atk_elem,int def_type, int def_lv) |
---|
212 | { |
---|
213 | |
---|
214 | if (atk_elem < 0 || atk_elem >= ELE_MAX) |
---|
215 | return 100; |
---|
216 | |
---|
217 | if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4) |
---|
218 | return 100; |
---|
219 | |
---|
220 | return attr_fix_table[def_lv-1][atk_elem][def_type]; |
---|
221 | } |
---|
222 | |
---|
223 | /*========================================== |
---|
224 | * Does attribute fix modifiers. |
---|
225 | * Added passing of the chars so that the status changes can affect it. [Skotlex] |
---|
226 | * Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks. |
---|
227 | *------------------------------------------*/ |
---|
228 | int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv) |
---|
229 | { |
---|
230 | struct status_change *sc=NULL, *tsc=NULL; |
---|
231 | int ratio; |
---|
232 | |
---|
233 | if (src) sc = status_get_sc(src); |
---|
234 | if (target) tsc = status_get_sc(target); |
---|
235 | |
---|
236 | if (atk_elem < 0 || atk_elem >= ELE_MAX) |
---|
237 | atk_elem = rand()%ELE_MAX; |
---|
238 | |
---|
239 | if (def_type < 0 || def_type > ELE_MAX || |
---|
240 | def_lv < 1 || def_lv > 4) { |
---|
241 | ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv); |
---|
242 | return damage; |
---|
243 | } |
---|
244 | |
---|
245 | ratio = attr_fix_table[def_lv-1][atk_elem][def_type]; |
---|
246 | if (sc && sc->count) |
---|
247 | { |
---|
248 | if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE) |
---|
249 | ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1]; |
---|
250 | if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND) |
---|
251 | ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1]; |
---|
252 | if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER) |
---|
253 | ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1]; |
---|
254 | } |
---|
255 | if (tsc && tsc->count) |
---|
256 | { |
---|
257 | if(tsc->data[SC_SPIDERWEB] && atk_elem == ELE_FIRE) |
---|
258 | { // [Celest] |
---|
259 | damage <<= 1; |
---|
260 | status_change_end(target, SC_SPIDERWEB, -1); |
---|
261 | } |
---|
262 | } |
---|
263 | return damage*ratio/100; |
---|
264 | } |
---|
265 | |
---|
266 | /*========================================== |
---|
267 | * _E?[W?Å?IvZ |
---|
268 | *------------------------------------------*/ |
---|
269 | int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag) |
---|
270 | { |
---|
271 | struct map_session_data *sd = NULL; |
---|
272 | struct status_change *sc; |
---|
273 | struct status_change_entry *sce; |
---|
274 | |
---|
275 | nullpo_retr(0, bl); |
---|
276 | |
---|
277 | if (!damage) |
---|
278 | return 0; |
---|
279 | |
---|
280 | if( mob_ksprotected(src, bl) ) |
---|
281 | return 0; |
---|
282 | |
---|
283 | if (bl->type == BL_PC) { |
---|
284 | sd=(struct map_session_data *)bl; |
---|
285 | //Special no damage states |
---|
286 | if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) |
---|
287 | damage -= damage*sd->special_state.no_weapon_damage/100; |
---|
288 | |
---|
289 | if(flag&BF_MAGIC && sd->special_state.no_magic_damage) |
---|
290 | damage -= damage*sd->special_state.no_magic_damage/100; |
---|
291 | |
---|
292 | if(flag&BF_MISC && sd->special_state.no_misc_damage) |
---|
293 | damage -= damage*sd->special_state.no_misc_damage/100; |
---|
294 | |
---|
295 | if(!damage) return 0; |
---|
296 | } |
---|
297 | |
---|
298 | if (skill_num == PA_PRESSURE) |
---|
299 | return damage; //This skill bypass everything else. |
---|
300 | |
---|
301 | sc = status_get_sc(bl); |
---|
302 | |
---|
303 | if (sc && sc->count) { |
---|
304 | //First, sc_*'s that reduce damage to 0. |
---|
305 | if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) |
---|
306 | { |
---|
307 | struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL]->val3; |
---|
308 | if (group) { |
---|
309 | if (--group->val2<=0) |
---|
310 | skill_delunitgroup(NULL,group); |
---|
311 | return 0; |
---|
312 | } |
---|
313 | status_change_end(bl,SC_SAFETYWALL,-1); |
---|
314 | } |
---|
315 | |
---|
316 | if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) |
---|
317 | return 0; |
---|
318 | |
---|
319 | if((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && |
---|
320 | !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && |
---|
321 | rand()%100 < sce->val2) |
---|
322 | { |
---|
323 | int delay; |
---|
324 | clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); |
---|
325 | // different delay depending on skill level [celest] |
---|
326 | if (sce->val1 <= 5) |
---|
327 | delay = 300; |
---|
328 | else if (sce->val1 > 5 && sce->val1 <= 9) |
---|
329 | delay = 200; |
---|
330 | else |
---|
331 | delay = 100; |
---|
332 | unit_set_walkdelay(bl, gettick(), delay, 1); |
---|
333 | |
---|
334 | if(sc->data[SC_SHRINK] && rand()%100<5*sce->val1) |
---|
335 | skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0); |
---|
336 | return 0; |
---|
337 | } |
---|
338 | |
---|
339 | if((sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON |
---|
340 | && skill_num != WS_CARTTERMINATION |
---|
341 | && rand()%100 < sce->val2) |
---|
342 | {// attack blocked by Parrying |
---|
343 | clif_skill_nodamage(bl,bl,LK_PARRYING,sce->val1,1); |
---|
344 | return 0; |
---|
345 | } |
---|
346 | |
---|
347 | if(sc->data[SC_DODGE] && !sc->opt1 && |
---|
348 | (flag&BF_LONG || sc->data[SC_SPURT]) |
---|
349 | && rand()%100 < 20) { |
---|
350 | if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge. |
---|
351 | clif_skill_nodamage(bl,bl,TK_DODGE,1,1); |
---|
352 | if (!sc->data[SC_COMBO]) |
---|
353 | sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); |
---|
354 | return 0; |
---|
355 | } |
---|
356 | |
---|
357 | if(sc->data[SC_HERMODE] && flag&BF_MAGIC) |
---|
358 | return 0; |
---|
359 | |
---|
360 | if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) |
---|
361 | return 0; |
---|
362 | |
---|
363 | if((sce=sc->data[SC_KAUPE]) && |
---|
364 | rand()%100 < sce->val2 && |
---|
365 | (src->type == BL_PC || !skill_num)) |
---|
366 | { //Kaupe only blocks all skills of players. |
---|
367 | clif_specialeffect(bl, 462, AREA); |
---|
368 | //Shouldn't end until Breaker's non-weapon part connects. |
---|
369 | if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) |
---|
370 | if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. |
---|
371 | status_change_end(bl, SC_KAUPE, -1); |
---|
372 | return 0; |
---|
373 | } |
---|
374 | |
---|
375 | //Begin Custom Jobs (blackmagic) |
---|
376 | |
---|
377 | //Display red flashing aura effect of Adept Blood Lust [Brain] |
---|
378 | if(sc->data[SC_LUST] && damage > 0){ |
---|
379 | clif_specialeffect(bl, 548, AREA); |
---|
380 | if(rand()%100 < 10) clif_specialeffect(bl, 455, AREA); //Red Lightnings, 1/10 attacks will show to prevent spam |
---|
381 | }; |
---|
382 | //Display blue flashing aura effect of Warlock Overwhelming Evil [Brain] |
---|
383 | if(sc->data[SC_OVERWHELMING] && damage > 0) |
---|
384 | clif_specialeffect(bl, 73, AREA); |
---|
385 | |
---|
386 | // AT-Field [Brainstorm] |
---|
387 | if(sc->data[SC_ATFIELD] && |
---|
388 | rand()%100 < sc->data[SC_ATFIELD]->val2) |
---|
389 | { //Blocks all skills. |
---|
390 | clif_specialeffect(bl, 438, AREA); |
---|
391 | //Shouldn't end until Breaker's non-weapon part connects. |
---|
392 | if (skill_num == ASC_BREAKER || |
---|
393 | skill_num == LK_SPIRALPIERCE || |
---|
394 | skill_num == CG_ARROWVULCAN || |
---|
395 | skill_num == SN_SHARPSHOOTING) |
---|
396 | if (--sc->data[SC_ATFIELD]->val3 <= 0) //We make it work like Safety Wall |
---|
397 | status_change_end(bl, SC_ATFIELD, -1); |
---|
398 | return 0; |
---|
399 | } |
---|
400 | //End Custom Jobs |
---|
401 | |
---|
402 | if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) |
---|
403 | && |
---|
404 | flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK)) |
---|
405 | { |
---|
406 | if (sce) { |
---|
407 | clif_specialeffect(bl, 462, AREA); |
---|
408 | skill_blown(src,bl,sce->val3,-1,0); |
---|
409 | } |
---|
410 | //Both need to be consumed if they are active. |
---|
411 | if (sce && --(sce->val2) <= 0) |
---|
412 | status_change_end(bl, SC_UTSUSEMI, -1); |
---|
413 | if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0) |
---|
414 | status_change_end(bl, SC_BUNSINJYUTSU, -1); |
---|
415 | return 0; |
---|
416 | } |
---|
417 | |
---|
418 | //Now damage increasing effects |
---|
419 | if(sc->data[SC_AETERNA] && skill_num != PF_SOULBURN){ |
---|
420 | damage<<=1; |
---|
421 | //Shouldn't end until Breaker's non-weapon part connects. |
---|
422 | if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) |
---|
423 | status_change_end( bl,SC_AETERNA,-1 ); |
---|
424 | } |
---|
425 | |
---|
426 | //Finally damage reductions.... |
---|
427 | if(sc->data[SC_ASSUMPTIO]){ |
---|
428 | if(map_flag_vs(bl->m)) |
---|
429 | damage=damage*2/3; //Receive 66% damage |
---|
430 | else |
---|
431 | damage>>=1; //Receive 50% damage |
---|
432 | } |
---|
433 | |
---|
434 | if(sc->data[SC_DEFENDER] && |
---|
435 | (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) |
---|
436 | damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100; |
---|
437 | |
---|
438 | if(sc->data[SC_ADJUSTMENT] && |
---|
439 | (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) |
---|
440 | damage -= 20*damage/100; |
---|
441 | |
---|
442 | if(sc->data[SC_FOGWALL]) { |
---|
443 | if(flag&BF_SKILL) //25% reduction |
---|
444 | damage -= 25*damage/100; |
---|
445 | else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) |
---|
446 | damage >>= 2; //75% reduction |
---|
447 | } |
---|
448 | |
---|
449 | if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER |
---|
450 | sce->val3&flag && sce->val4&flag) |
---|
451 | damage -= damage*sc->data[SC_ARMOR]->val2/100; |
---|
452 | |
---|
453 | if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON |
---|
454 | && skill_num != WS_CARTTERMINATION) |
---|
455 | { |
---|
456 | struct status_data *status = status_get_status_data(bl); |
---|
457 | int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval |
---|
458 | per /=20; //Uses 20% SP intervals. |
---|
459 | //SP Cost: 1% + 0.5% per every 20% SP |
---|
460 | if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) |
---|
461 | status_change_end( bl,SC_ENERGYCOAT,-1 ); |
---|
462 | //Reduction: 6% + 6% every 20% |
---|
463 | damage -= damage * 6 * (1+per) / 100; |
---|
464 | } |
---|
465 | |
---|
466 | if((sce=sc->data[SC_REJECTSWORD]) && flag&BF_WEAPON && |
---|
467 | // Fixed the condition check [Aalye] |
---|
468 | (src->type!=BL_PC || ( |
---|
469 | ((TBL_PC *)src)->status.weapon == W_DAGGER || |
---|
470 | ((TBL_PC *)src)->status.weapon == W_1HSWORD || |
---|
471 | ((TBL_PC *)src)->status.weapon == W_2HSWORD |
---|
472 | )) && |
---|
473 | rand()%100 < sce->val2 |
---|
474 | ){ |
---|
475 | damage = damage*50/100; |
---|
476 | status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0)); |
---|
477 | clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1); |
---|
478 | if(--(sce->val3)<=0) |
---|
479 | status_change_end(bl, SC_REJECTSWORD, -1); |
---|
480 | } |
---|
481 | |
---|
482 | //Finally Kyrie because it may, or not, reduce damage to 0. |
---|
483 | if((sce = sc->data[SC_KYRIE]) && damage > 0){ |
---|
484 | sce->val2-=damage; |
---|
485 | if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){ |
---|
486 | if(sce->val2>=0) |
---|
487 | damage=0; |
---|
488 | else |
---|
489 | damage=-sce->val2; |
---|
490 | } |
---|
491 | if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT) |
---|
492 | status_change_end(bl, SC_KYRIE, -1); |
---|
493 | } |
---|
494 | |
---|
495 | if (!damage) return 0; |
---|
496 | |
---|
497 | //Probably not the most correct place, but it'll do here |
---|
498 | //(since battle_drain is strictly for players currently) |
---|
499 | if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && |
---|
500 | rand()%100 < sce->val3) |
---|
501 | status_heal(src, damage*sce->val4/100, 0, 3); |
---|
502 | |
---|
503 | } |
---|
504 | //SC effects from caster side. Currently none. |
---|
505 | /* |
---|
506 | sc = status_get_sc(src); |
---|
507 | if (sc && sc->count) { |
---|
508 | } |
---|
509 | */ |
---|
510 | if (battle_config.pk_mode && sd && bl->type == BL_PC && damage) |
---|
511 | { |
---|
512 | if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] |
---|
513 | if (flag&BF_WEAPON) |
---|
514 | damage = damage * battle_config.pk_weapon_damage_rate/100; |
---|
515 | if (flag&BF_MAGIC) |
---|
516 | damage = damage * battle_config.pk_magic_damage_rate/100; |
---|
517 | if (flag&BF_MISC) |
---|
518 | damage = damage * battle_config.pk_misc_damage_rate/100; |
---|
519 | } else { //Normal attacks get reductions based on range. |
---|
520 | if (flag & BF_SHORT) |
---|
521 | damage = damage * battle_config.pk_short_damage_rate/100; |
---|
522 | if (flag & BF_LONG) |
---|
523 | damage = damage * battle_config.pk_long_damage_rate/100; |
---|
524 | } |
---|
525 | if(!damage) damage = 1; |
---|
526 | } |
---|
527 | |
---|
528 | if(battle_config.skill_min_damage && damage > 0 && damage < div_) |
---|
529 | { |
---|
530 | if ((flag&BF_WEAPON && battle_config.skill_min_damage&1) |
---|
531 | || (flag&BF_MAGIC && battle_config.skill_min_damage&2) |
---|
532 | || (flag&BF_MISC && battle_config.skill_min_damage&4) |
---|
533 | ) |
---|
534 | damage = div_; |
---|
535 | } |
---|
536 | |
---|
537 | if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) { |
---|
538 | if (damage > 0 ) |
---|
539 | mobskill_event((TBL_MOB*)bl,src,gettick(),flag); |
---|
540 | if (skill_num) |
---|
541 | mobskill_event((TBL_MOB*)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16)); |
---|
542 | } |
---|
543 | |
---|
544 | return damage; |
---|
545 | } |
---|
546 | |
---|
547 | /*========================================== |
---|
548 | * Calculates GVG related damage adjustments. |
---|
549 | *------------------------------------------*/ |
---|
550 | int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag) |
---|
551 | { |
---|
552 | struct mob_data *md = NULL; |
---|
553 | int class_; |
---|
554 | |
---|
555 | if (!damage) //No reductions to make. |
---|
556 | return 0; |
---|
557 | |
---|
558 | class_ = status_get_class(bl); |
---|
559 | |
---|
560 | if (bl->type == BL_MOB) |
---|
561 | md=(struct mob_data *)bl; |
---|
562 | |
---|
563 | if(md && md->guardian_data) { |
---|
564 | if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) |
---|
565 | //Skill immunity. |
---|
566 | switch (skill_num) { |
---|
567 | case MO_TRIPLEATTACK: |
---|
568 | case HW_GRAVITATION: |
---|
569 | break; |
---|
570 | default: |
---|
571 | return 0; |
---|
572 | } |
---|
573 | if(src->type != BL_MOB) { |
---|
574 | struct guild *g=guild_search(status_get_guild_id(src)); |
---|
575 | if (!g) return 0; |
---|
576 | if (class_ == MOBID_EMPERIUM && guild_checkskill(g,GD_APPROVAL) <= 0) |
---|
577 | return 0; |
---|
578 | if (battle_config.guild_max_castles && |
---|
579 | guild_checkcastles(g)>=battle_config.guild_max_castles) |
---|
580 | return 0; // [MouseJstr] |
---|
581 | } |
---|
582 | } |
---|
583 | |
---|
584 | switch (skill_num) { |
---|
585 | //Skills with no damage reduction. |
---|
586 | case PA_PRESSURE: |
---|
587 | case HW_GRAVITATION: |
---|
588 | case NJ_ZENYNAGE: |
---|
589 | break; |
---|
590 | default: |
---|
591 | if (md && md->guardian_data) { |
---|
592 | damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; |
---|
593 | } |
---|
594 | if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] |
---|
595 | if (flag&BF_WEAPON) |
---|
596 | damage = damage * battle_config.gvg_weapon_damage_rate/100; |
---|
597 | if (flag&BF_MAGIC) |
---|
598 | damage = damage * battle_config.gvg_magic_damage_rate/100; |
---|
599 | if (flag&BF_MISC) |
---|
600 | damage = damage * battle_config.gvg_misc_damage_rate/100; |
---|
601 | } else { //Normal attacks get reductions based on range. |
---|
602 | if (flag & BF_SHORT) |
---|
603 | damage = damage * battle_config.gvg_short_damage_rate/100; |
---|
604 | if (flag & BF_LONG) |
---|
605 | damage = damage * battle_config.gvg_long_damage_rate/100; |
---|
606 | } |
---|
607 | if(!damage) damage = 1; |
---|
608 | } |
---|
609 | return damage; |
---|
610 | } |
---|
611 | |
---|
612 | /*========================================== |
---|
613 | * HP/SPzûÌvZ |
---|
614 | *------------------------------------------*/ |
---|
615 | static int battle_calc_drain(int damage, int rate, int per) |
---|
616 | { |
---|
617 | int diff = 0; |
---|
618 | |
---|
619 | if (per && rand()%1000 < rate) { |
---|
620 | diff = (damage * per) / 100; |
---|
621 | if (diff == 0) { |
---|
622 | if (per > 0) |
---|
623 | diff = 1; |
---|
624 | else |
---|
625 | diff = -1; |
---|
626 | } |
---|
627 | } |
---|
628 | return diff; |
---|
629 | } |
---|
630 | |
---|
631 | /*========================================== |
---|
632 | * ?Cû_E?[W |
---|
633 | *------------------------------------------*/ |
---|
634 | int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) |
---|
635 | { |
---|
636 | int damage,skill; |
---|
637 | struct status_data *status = status_get_status_data(target); |
---|
638 | int weapon; |
---|
639 | damage = dmg; |
---|
640 | |
---|
641 | nullpo_retr(0, sd); |
---|
642 | |
---|
643 | if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && |
---|
644 | (status->race==RC_UNDEAD || status->race==RC_DEMON) ) |
---|
645 | damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn |
---|
646 | //damage += (skill * 3); |
---|
647 | |
---|
648 | if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) { |
---|
649 | damage += (skill * 4); |
---|
650 | if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER) |
---|
651 | damage += sd->status.str; |
---|
652 | } |
---|
653 | //Begin Custom Jobs (blackmagic) |
---|
654 | //Warlock Touch of Corruption (Mage-Monster Killer passive skill) [Brainstorm] |
---|
655 | if((skill = pc_checkskill(sd,WL_CORRUPTION)) > 0 && target->type==BL_MOB ) |
---|
656 | damage += (skill * (status->int_/10)); |
---|
657 | //end custom job |
---|
658 | |
---|
659 | if(type == 0) |
---|
660 | weapon = sd->weapontype1; |
---|
661 | else |
---|
662 | weapon = sd->weapontype2; |
---|
663 | switch(weapon) |
---|
664 | { |
---|
665 | case W_DAGGER: |
---|
666 | case W_1HSWORD: |
---|
667 | if((skill = pc_checkskill(sd,SM_SWORD)) > 0) |
---|
668 | damage += (skill * 4); |
---|
669 | break; |
---|
670 | case W_2HSWORD: |
---|
671 | if((skill = pc_checkskill(sd,SM_TWOHAND)) > 0) |
---|
672 | damage += (skill * 4); |
---|
673 | break; |
---|
674 | case W_1HSPEAR: |
---|
675 | case W_2HSPEAR: |
---|
676 | if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) { |
---|
677 | if(!pc_isriding(sd)) |
---|
678 | damage += (skill * 4); |
---|
679 | else |
---|
680 | damage += (skill * 5); |
---|
681 | } |
---|
682 | break; |
---|
683 | case W_1HAXE: |
---|
684 | case W_2HAXE: |
---|
685 | if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) |
---|
686 | damage += (skill * 3); |
---|
687 | break; |
---|
688 | case W_MACE: |
---|
689 | case W_2HMACE: |
---|
690 | if((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0) |
---|
691 | damage += (skill * 3); |
---|
692 | break; |
---|
693 | case W_FIST: |
---|
694 | if((skill = pc_checkskill(sd,TK_RUN)) > 0) |
---|
695 | damage += (skill * 10); |
---|
696 | // No break, fallthrough to Knuckles |
---|
697 | case W_KNUCKLE: |
---|
698 | if((skill = pc_checkskill(sd,MO_IRONHAND)) > 0) |
---|
699 | damage += (skill * 3); |
---|
700 | break; |
---|
701 | case W_MUSICAL: |
---|
702 | if((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0) |
---|
703 | damage += (skill * 3); |
---|
704 | break; |
---|
705 | case W_WHIP: |
---|
706 | if((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0) |
---|
707 | damage += (skill * 3); |
---|
708 | break; |
---|
709 | case W_BOOK: |
---|
710 | if((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0) |
---|
711 | damage += (skill * 3); |
---|
712 | break; |
---|
713 | case W_KATAR: |
---|
714 | if((skill = pc_checkskill(sd,AS_KATAR)) > 0) |
---|
715 | damage += (skill * 3); |
---|
716 | break; |
---|
717 | } |
---|
718 | |
---|
719 | return damage; |
---|
720 | } |
---|
721 | /*========================================== |
---|
722 | * Calculates the standard damage of a normal attack assuming it hits, |
---|
723 | * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex] |
---|
724 | *------------------------------------------ |
---|
725 | * Pass damage2 as NULL to not calc it. |
---|
726 | * Flag values: |
---|
727 | * &1: Critical hit |
---|
728 | * &2: Arrow attack |
---|
729 | * &4: Skill is Magic Crasher |
---|
730 | * &8: Skip target size adjustment (Extremity Fist?) |
---|
731 | *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) |
---|
732 | */ |
---|
733 | static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) |
---|
734 | { |
---|
735 | unsigned short atkmin=0, atkmax=0; |
---|
736 | short type = 0; |
---|
737 | int damage = 0; |
---|
738 | |
---|
739 | if (!sd) |
---|
740 | { //Mobs/Pets |
---|
741 | if(flag&4) |
---|
742 | { |
---|
743 | atkmin = status->matk_min; |
---|
744 | atkmax = status->matk_max; |
---|
745 | } else { |
---|
746 | atkmin = wa->atk; |
---|
747 | atkmax = wa->atk2; |
---|
748 | } |
---|
749 | if (atkmin > atkmax) |
---|
750 | atkmin = atkmax; |
---|
751 | } else { //PCs |
---|
752 | atkmax = wa->atk; |
---|
753 | type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; |
---|
754 | |
---|
755 | if (!(flag&1) || (flag&2)) |
---|
756 | { //Normal attacks |
---|
757 | atkmin = status->dex; |
---|
758 | |
---|
759 | if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) |
---|
760 | atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100; |
---|
761 | |
---|
762 | if (atkmin > atkmax) |
---|
763 | atkmin = atkmax; |
---|
764 | |
---|
765 | if(flag&2 && !(flag&16)) |
---|
766 | { //Bows |
---|
767 | atkmin = atkmin*atkmax/100; |
---|
768 | if (atkmin > atkmax) |
---|
769 | atkmax = atkmin; |
---|
770 | } |
---|
771 | } |
---|
772 | } |
---|
773 | |
---|
774 | if (sc && sc->data[SC_MAXIMIZEPOWER]) |
---|
775 | atkmin = atkmax; |
---|
776 | |
---|
777 | //Weapon Damage calculation |
---|
778 | if (!(flag&1)) |
---|
779 | damage = (atkmax>atkmin? rand()%(atkmax-atkmin):0)+atkmin; |
---|
780 | else |
---|
781 | damage = atkmax; |
---|
782 | |
---|
783 | if (sd) |
---|
784 | { |
---|
785 | //rodatazone says the range is 0~arrow_atk-1 for non crit |
---|
786 | if (flag&2 && sd->arrow_atk) |
---|
787 | damage += ((flag&1)?sd->arrow_atk:rand()%sd->arrow_atk); |
---|
788 | |
---|
789 | //SizeFix only for players |
---|
790 | if (!(sd->special_state.no_sizefix || (flag&8))) |
---|
791 | damage = damage*(type==EQI_HAND_L? |
---|
792 | sd->left_weapon.atkmods[t_size]: |
---|
793 | sd->right_weapon.atkmods[t_size])/100; |
---|
794 | } |
---|
795 | |
---|
796 | //Finally, add baseatk |
---|
797 | if(flag&4) |
---|
798 | damage += status->matk_min; |
---|
799 | else |
---|
800 | damage += status->batk; |
---|
801 | |
---|
802 | //rodatazone says that Overrefine bonuses are part of baseatk |
---|
803 | //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. |
---|
804 | if(sd) { |
---|
805 | if (type == EQI_HAND_L) { |
---|
806 | if(sd->left_weapon.overrefine) |
---|
807 | damage += rand()%sd->left_weapon.overrefine+1; |
---|
808 | if (sd->weapon_atk_rate[sd->weapontype2]) |
---|
809 | damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;; |
---|
810 | } else { //Right hand |
---|
811 | if(sd->right_weapon.overrefine) |
---|
812 | damage += rand()%sd->right_weapon.overrefine+1; |
---|
813 | if (sd->weapon_atk_rate[sd->weapontype1]) |
---|
814 | damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;; |
---|
815 | } |
---|
816 | } |
---|
817 | return damage; |
---|
818 | } |
---|
819 | |
---|
820 | /*========================================== |
---|
821 | * Consumes ammo for the given skill. |
---|
822 | *------------------------------------------*/ |
---|
823 | void battle_consume_ammo(TBL_PC*sd, int skill, int lv) |
---|
824 | { |
---|
825 | int qty=1; |
---|
826 | if (!battle_config.arrow_decrement) |
---|
827 | return; |
---|
828 | |
---|
829 | if (skill) |
---|
830 | { |
---|
831 | qty = skill_get_ammo_qty(skill, lv); |
---|
832 | if (!qty) qty = 1; |
---|
833 | } |
---|
834 | |
---|
835 | if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition |
---|
836 | pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0); |
---|
837 | } |
---|
838 | |
---|
839 | static int battle_range_type( |
---|
840 | struct block_list *src, struct block_list *target, |
---|
841 | int skill_num, int skill_lv) |
---|
842 | { //Skill Range Criteria |
---|
843 | if (battle_config.skillrange_by_distance && |
---|
844 | (src->type&battle_config.skillrange_by_distance) |
---|
845 | ) { //based on distance between src/target [Skotlex] |
---|
846 | if (check_distance_bl(src, target, 5)) |
---|
847 | return BF_SHORT; |
---|
848 | return BF_LONG; |
---|
849 | } |
---|
850 | //based on used skill's range |
---|
851 | if (skill_get_range2(src, skill_num, skill_lv) < 5) |
---|
852 | return BF_SHORT; |
---|
853 | return BF_LONG; |
---|
854 | } |
---|
855 | |
---|
856 | static int battle_blewcount_bonus(struct map_session_data *sd, int skill_num) |
---|
857 | { |
---|
858 | int i; |
---|
859 | if (!sd->skillblown[0].id) |
---|
860 | return 0; |
---|
861 | //Apply the bonus blewcount. [Skotlex] |
---|
862 | for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { |
---|
863 | if (sd->skillblown[i].id == skill_num) |
---|
864 | return sd->skillblown[i].val; |
---|
865 | } |
---|
866 | return 0; |
---|
867 | } |
---|
868 | |
---|
869 | struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag); |
---|
870 | struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag); |
---|
871 | |
---|
872 | //For quick div adjustment. |
---|
873 | #define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } |
---|
874 | /*========================================== |
---|
875 | * battle_calc_weapon_attack (by Skotlex) |
---|
876 | *------------------------------------------*/ |
---|
877 | static struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int wflag) |
---|
878 | { |
---|
879 | unsigned int skillratio = 100; //Skill dmg modifiers. |
---|
880 | short skill=0; |
---|
881 | short s_ele, s_ele_, t_class; |
---|
882 | int i, nk; |
---|
883 | |
---|
884 | struct map_session_data *sd, *tsd; |
---|
885 | struct Damage wd; |
---|
886 | struct status_change *sc = status_get_sc(src); |
---|
887 | struct status_change *tsc = status_get_sc(target); |
---|
888 | struct status_data *sstatus = status_get_status_data(src); |
---|
889 | struct status_data *tstatus = status_get_status_data(target); |
---|
890 | struct { |
---|
891 | unsigned hit : 1; //the attack Hit? (not a miss) |
---|
892 | unsigned cri : 1; //Critical hit |
---|
893 | unsigned idef : 1; //Ignore defense |
---|
894 | unsigned idef2 : 1; //Ignore defense (left weapon) |
---|
895 | unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick) |
---|
896 | unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50 |
---|
897 | unsigned infdef : 1; //Infinite defense (plants) |
---|
898 | unsigned arrow : 1; //Attack is arrow-based |
---|
899 | unsigned rh : 1; //Attack considers right hand (wd.damage) |
---|
900 | unsigned lh : 1; //Attack considers left hand (wd.damage2) |
---|
901 | unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) |
---|
902 | } flag; |
---|
903 | |
---|
904 | memset(&wd,0,sizeof(wd)); |
---|
905 | memset(&flag,0,sizeof(flag)); |
---|
906 | |
---|
907 | if(src==NULL || target==NULL) |
---|
908 | { |
---|
909 | nullpo_info(NLP_MARK); |
---|
910 | return wd; |
---|
911 | } |
---|
912 | //Initial flag |
---|
913 | flag.rh=1; |
---|
914 | flag.weapon=1; |
---|
915 | flag.infdef=(tstatus->mode&MD_PLANT?1:0); |
---|
916 | |
---|
917 | //Initial Values |
---|
918 | wd.type=0; //Normal attack |
---|
919 | wd.div_=skill_num?skill_get_num(skill_num,skill_lv):1; |
---|
920 | wd.amotion=(skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. |
---|
921 | if(skill_num == KN_AUTOCOUNTER) |
---|
922 | wd.amotion >>= 1; |
---|
923 | wd.dmotion=tstatus->dmotion; |
---|
924 | wd.blewcount=skill_get_blewcount(skill_num,skill_lv); |
---|
925 | wd.flag = BF_WEAPON; //Initial Flag |
---|
926 | wd.flag|= skill_num?BF_SKILL:BF_NORMAL; |
---|
927 | wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later |
---|
928 | nk = skill_get_nk(skill_num); |
---|
929 | flag.hit = nk&NK_IGNORE_FLEE?1:0; |
---|
930 | flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0; |
---|
931 | |
---|
932 | if (sc && !sc->count) |
---|
933 | sc = NULL; //Skip checking as there are no status changes active. |
---|
934 | if (tsc && !tsc->count) |
---|
935 | tsc = NULL; //Skip checking as there are no status changes active. |
---|
936 | |
---|
937 | sd = BL_CAST(BL_PC, src); |
---|
938 | tsd = BL_CAST(BL_PC, target); |
---|
939 | |
---|
940 | if(sd) |
---|
941 | wd.blewcount += battle_blewcount_bonus(sd, skill_num); |
---|
942 | |
---|
943 | //Set miscellaneous data that needs be filled regardless of hit/miss |
---|
944 | if( |
---|
945 | (sd && sd->state.arrow_atk) || |
---|
946 | (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3)) |
---|
947 | ) |
---|
948 | flag.arrow = 1; |
---|
949 | |
---|
950 | if(skill_num){ |
---|
951 | wd.flag |= battle_range_type(src, target, skill_num, skill_lv); |
---|
952 | switch(skill_num) |
---|
953 | { |
---|
954 | case MO_FINGEROFFENSIVE: |
---|
955 | if(sd) { |
---|
956 | if (battle_config.finger_offensive_type) |
---|
957 | wd.div_ = 1; |
---|
958 | else |
---|
959 | wd.div_ = sd->spiritball_old; |
---|
960 | } |
---|
961 | break; |
---|
962 | case HT_PHANTASMIC: |
---|
963 | //Since these do not consume ammo, they need to be explicitly set as arrow attacks. |
---|
964 | flag.arrow = 1; |
---|
965 | break; |
---|
966 | |
---|
967 | case CR_SHIELDBOOMERANG: |
---|
968 | case PA_SHIELDCHAIN: |
---|
969 | flag.weapon = 0; |
---|
970 | break; |
---|
971 | |
---|
972 | case KN_PIERCE: |
---|
973 | wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); |
---|
974 | break; |
---|
975 | |
---|
976 | case TF_DOUBLE: //For NPC used skill. |
---|
977 | case GS_CHAINACTION: |
---|
978 | wd.type = 0x08; |
---|
979 | break; |
---|
980 | |
---|
981 | case GS_GROUNDDRIFT: |
---|
982 | case KN_SPEARSTAB: |
---|
983 | case KN_BOWLINGBASH: |
---|
984 | case MO_BALKYOUNG: |
---|
985 | case TK_TURNKICK: |
---|
986 | wd.blewcount=0; |
---|
987 | break; |
---|
988 | |
---|
989 | case KN_AUTOCOUNTER: |
---|
990 | wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; |
---|
991 | break; |
---|
992 | |
---|
993 | case NPC_CRITICALSLASH: |
---|
994 | flag.cri = 1; //Always critical skill. |
---|
995 | break; |
---|
996 | } |
---|
997 | } else //Range for normal attacks. |
---|
998 | wd.flag |= flag.arrow?BF_LONG:BF_SHORT; |
---|
999 | |
---|
1000 | if (!skill_num && tstatus->flee2 && rand()%1000 < tstatus->flee2) |
---|
1001 | { //Check for Lucky Dodge |
---|
1002 | wd.type=0x0b; |
---|
1003 | wd.dmg_lv=ATK_LUCKY; |
---|
1004 | if (wd.div_ < 0) wd.div_*=-1; |
---|
1005 | return wd; |
---|
1006 | } |
---|
1007 | |
---|
1008 | t_class = status_get_class(target); |
---|
1009 | s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv); |
---|
1010 | if (!skill_num || s_ele == -1) { //Take weapon's element |
---|
1011 | s_ele = sstatus->rhw.ele; |
---|
1012 | s_ele_ = sstatus->lhw.ele; |
---|
1013 | if (flag.arrow && sd && sd->arrow_ele) |
---|
1014 | s_ele = sd->arrow_ele; |
---|
1015 | } else if (s_ele == -2) { //Use enchantment's element |
---|
1016 | s_ele = s_ele_ = status_get_attack_sc_element(src,sc); |
---|
1017 | } |
---|
1018 | if (skill_num == GS_GROUNDDRIFT) |
---|
1019 | s_ele = s_ele_ = wflag; //element comes in flag. |
---|
1020 | |
---|
1021 | if(!skill_num) |
---|
1022 | { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2) |
---|
1023 | if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0) |
---|
1024 | { |
---|
1025 | flag.rh=0; |
---|
1026 | flag.lh=1; |
---|
1027 | } |
---|
1028 | if (sstatus->lhw.atk) |
---|
1029 | flag.lh=1; |
---|
1030 | } |
---|
1031 | |
---|
1032 | //Check for critical |
---|
1033 | if(!flag.cri && sstatus->cri && |
---|
1034 | (!skill_num || |
---|
1035 | skill_num == KN_AUTOCOUNTER || |
---|
1036 | skill_num == SN_SHARPSHOOTING || |
---|
1037 | skill_num == NJ_KIRIKAGE)) |
---|
1038 | { |
---|
1039 | short cri = sstatus->cri; |
---|
1040 | if (sd) |
---|
1041 | { |
---|
1042 | cri+= sd->critaddrace[tstatus->race]; |
---|
1043 | if(flag.arrow) |
---|
1044 | cri += sd->arrow_cri; |
---|
1045 | if(sd->status.weapon == W_KATAR) |
---|
1046 | cri <<=1; |
---|
1047 | } |
---|
1048 | //The official equation is *2, but that only applies when sd's do critical. |
---|
1049 | //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob |
---|
1050 | cri -= tstatus->luk*(!sd&&tsd?3:2); |
---|
1051 | |
---|
1052 | if(tsc) |
---|
1053 | { |
---|
1054 | if (tsc->data[SC_SLEEP]) |
---|
1055 | cri <<=1; |
---|
1056 | } |
---|
1057 | switch (skill_num) |
---|
1058 | { |
---|
1059 | case KN_AUTOCOUNTER: |
---|
1060 | if(battle_config.auto_counter_type && |
---|
1061 | (battle_config.auto_counter_type&src->type)) |
---|
1062 | flag.cri = 1; |
---|
1063 | else |
---|
1064 | cri <<= 1; |
---|
1065 | break; |
---|
1066 | case SN_SHARPSHOOTING: |
---|
1067 | cri += 200; |
---|
1068 | break; |
---|
1069 | case NJ_KIRIKAGE: |
---|
1070 | cri += 250 + 50*skill_lv; |
---|
1071 | break; |
---|
1072 | } |
---|
1073 | if(tsd && tsd->critical_def) |
---|
1074 | cri = cri*(100-tsd->critical_def)/100; |
---|
1075 | if (rand()%1000 < cri) |
---|
1076 | flag.cri= 1; |
---|
1077 | } |
---|
1078 | if (flag.cri) |
---|
1079 | { |
---|
1080 | wd.type = 0x0a; |
---|
1081 | flag.idef = flag.idef2 = flag.hit = 1; |
---|
1082 | } else { //Check for Perfect Hit |
---|
1083 | if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit) |
---|
1084 | flag.hit = 1; |
---|
1085 | if (sc && sc->data[SC_FUSION]) { |
---|
1086 | flag.hit = 1; //SG_FUSION always hit [Komurka] |
---|
1087 | flag.idef = flag.idef2 = 1; //def ignore [Komurka] |
---|
1088 | } |
---|
1089 | if (skill_num && !flag.hit) |
---|
1090 | switch(skill_num) |
---|
1091 | { |
---|
1092 | case AS_SPLASHER: |
---|
1093 | if (wflag) // Always hits the one exploding. |
---|
1094 | break; |
---|
1095 | flag.hit = 1; |
---|
1096 | break; |
---|
1097 | case CR_SHIELDBOOMERANG: |
---|
1098 | if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) |
---|
1099 | flag.hit = 1; |
---|
1100 | break; |
---|
1101 | case 0: |
---|
1102 | //If flag, this is splash damage from Baphomet Card and it always hits. |
---|
1103 | if (wflag) |
---|
1104 | flag.hit = 1; |
---|
1105 | break; |
---|
1106 | } |
---|
1107 | if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT) |
---|
1108 | flag.hit = 1; |
---|
1109 | } |
---|
1110 | |
---|
1111 | if (!flag.hit) |
---|
1112 | { //Hit/Flee calculation |
---|
1113 | short |
---|
1114 | flee = tstatus->flee, |
---|
1115 | hitrate=80; //Default hitrate |
---|
1116 | |
---|
1117 | if(battle_config.agi_penalty_type && |
---|
1118 | battle_config.agi_penalty_target&target->type) |
---|
1119 | { |
---|
1120 | unsigned char attacker_count; //256 max targets should be a sane max |
---|
1121 | attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv); |
---|
1122 | if(attacker_count >= battle_config.agi_penalty_count) |
---|
1123 | { |
---|
1124 | if (battle_config.agi_penalty_type == 1) |
---|
1125 | flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; |
---|
1126 | else //asume type 2: absolute reduction |
---|
1127 | flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; |
---|
1128 | if(flee < 1) flee = 1; |
---|
1129 | } |
---|
1130 | } |
---|
1131 | |
---|
1132 | hitrate+= sstatus->hit - flee; |
---|
1133 | |
---|
1134 | if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks. |
---|
1135 | tsc && tsc->data[SC_FOGWALL]) |
---|
1136 | hitrate -= 50; |
---|
1137 | |
---|
1138 | if(sd && flag.arrow) |
---|
1139 | hitrate += sd->arrow_hit; |
---|
1140 | if(skill_num) |
---|
1141 | switch(skill_num) |
---|
1142 | { //Hit skill modifiers |
---|
1143 | //It is proven that bonus is applied on final hitrate, not hit. |
---|
1144 | case SM_BASH: |
---|
1145 | hitrate += hitrate * 5 * skill_lv / 100; |
---|
1146 | break; |
---|
1147 | case SM_MAGNUM: |
---|
1148 | hitrate += hitrate * 10 * skill_lv / 100; |
---|
1149 | break; |
---|
1150 | case KN_AUTOCOUNTER: |
---|
1151 | case PA_SHIELDCHAIN: |
---|
1152 | case NPC_WATERATTACK: |
---|
1153 | case NPC_GROUNDATTACK: |
---|
1154 | case NPC_FIREATTACK: |
---|
1155 | case NPC_WINDATTACK: |
---|
1156 | case NPC_POISONATTACK: |
---|
1157 | case NPC_HOLYATTACK: |
---|
1158 | case NPC_DARKNESSATTACK: |
---|
1159 | case NPC_UNDEADATTACK: |
---|
1160 | case NPC_TELEKINESISATTACK: |
---|
1161 | case NPC_BLEEDING: |
---|
1162 | hitrate += hitrate * 20 / 100; |
---|
1163 | break; |
---|
1164 | case KN_PIERCE: |
---|
1165 | hitrate += hitrate * 5 * skill_lv / 100; |
---|
1166 | break; |
---|
1167 | case AS_SONICBLOW: |
---|
1168 | if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) |
---|
1169 | hitrate += hitrate * 50 / 100; |
---|
1170 | break; |
---|
1171 | } |
---|
1172 | |
---|
1173 | // Weaponry Research hidden bonus |
---|
1174 | if (sd && (skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) |
---|
1175 | hitrate += hitrate * ( 2 * skill ) / 100; |
---|
1176 | |
---|
1177 | hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); |
---|
1178 | |
---|
1179 | if(rand()%100 >= hitrate) |
---|
1180 | wd.dmg_lv = ATK_FLEE; |
---|
1181 | else |
---|
1182 | flag.hit = 1; |
---|
1183 | } //End hit/miss calculation |
---|
1184 | |
---|
1185 | if (flag.hit && !flag.infdef) //No need to do the math for plants |
---|
1186 | { //Hitting attack |
---|
1187 | |
---|
1188 | //Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. |
---|
1189 | //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc |
---|
1190 | #define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; } |
---|
1191 | #define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } |
---|
1192 | //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage |
---|
1193 | #define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; } |
---|
1194 | #define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } |
---|
1195 | //Adds an absolute value to damage. 100 = +100 damage |
---|
1196 | #define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; } |
---|
1197 | #define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; } |
---|
1198 | |
---|
1199 | switch (skill_num) |
---|
1200 | { //Calc base damage according to skill |
---|
1201 | case NJ_ISSEN: |
---|
1202 | wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35); |
---|
1203 | wd.damage2 = 0; |
---|
1204 | status_set_hp(src, 1, 0); |
---|
1205 | break; |
---|
1206 | case PA_SACRIFICE: |
---|
1207 | wd.damage = sstatus->max_hp* 9/100; |
---|
1208 | status_zap(src, wd.damage, 0);//Damage to self is always 9% |
---|
1209 | wd.damage2 = 0; |
---|
1210 | |
---|
1211 | if (sc && sc->data[SC_SACRIFICE]) |
---|
1212 | { |
---|
1213 | if (--sc->data[SC_SACRIFICE]->val2 <= 0) |
---|
1214 | status_change_end(src, SC_SACRIFICE,-1); |
---|
1215 | } |
---|
1216 | break; |
---|
1217 | case LK_SPIRALPIERCE: |
---|
1218 | if (sd) { |
---|
1219 | short index = sd->equip_index[EQI_HAND_R]; |
---|
1220 | |
---|
1221 | if (index >= 0 && |
---|
1222 | sd->inventory_data[index] && |
---|
1223 | sd->inventory_data[index]->type == IT_WEAPON) |
---|
1224 | wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight |
---|
1225 | } else |
---|
1226 | wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2 |
---|
1227 | |
---|
1228 | ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only. |
---|
1229 | i = sstatus->str/10; |
---|
1230 | i*=i; |
---|
1231 | ATK_ADD(i); //Add str bonus. |
---|
1232 | switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection? |
---|
1233 | case 0: //Small: 125% |
---|
1234 | ATK_RATE(125); |
---|
1235 | break; |
---|
1236 | //case 1: //Medium: 100% |
---|
1237 | case 2: //Large: 75% |
---|
1238 | ATK_RATE(75); |
---|
1239 | break; |
---|
1240 | } |
---|
1241 | break; |
---|
1242 | case CR_SHIELDBOOMERANG: |
---|
1243 | case PA_SHIELDCHAIN: |
---|
1244 | wd.damage = sstatus->batk; |
---|
1245 | if (sd) { |
---|
1246 | short index = sd->equip_index[EQI_HAND_L]; |
---|
1247 | |
---|
1248 | if (index >= 0 && |
---|
1249 | sd->inventory_data[index] && |
---|
1250 | sd->inventory_data[index]->type == IT_ARMOR) |
---|
1251 | ATK_ADD(sd->inventory_data[index]->weight/10); |
---|
1252 | break; |
---|
1253 | } else |
---|
1254 | ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 |
---|
1255 | break; |
---|
1256 | case HFLI_SBR44: //[orn] |
---|
1257 | if(src->type == BL_HOM) { |
---|
1258 | wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ; |
---|
1259 | break; |
---|
1260 | } |
---|
1261 | default: |
---|
1262 | { |
---|
1263 | i = (flag.cri?1:0)| |
---|
1264 | (flag.arrow?2:0)| |
---|
1265 | (skill_num == HW_MAGICCRASHER?4:0)| |
---|
1266 | (!skill_num && sc && sc->data[SC_CHANGE]?4:0)| |
---|
1267 | (skill_num == MO_EXTREMITYFIST?8:0)| |
---|
1268 | (sc && sc->data[SC_WEAPONPERFECTION]?8:0); |
---|
1269 | if (flag.arrow && sd) |
---|
1270 | switch(sd->status.weapon) { |
---|
1271 | case W_BOW: |
---|
1272 | case W_REVOLVER: |
---|
1273 | case W_GATLING: |
---|
1274 | case W_SHOTGUN: |
---|
1275 | case W_GRENADE: |
---|
1276 | break; |
---|
1277 | default: |
---|
1278 | i |= 16; // for ex. shuriken must not be influenced by DEX |
---|
1279 | } |
---|
1280 | wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); |
---|
1281 | if (flag.lh) |
---|
1282 | wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); |
---|
1283 | |
---|
1284 | if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets |
---|
1285 | if(wflag>0) |
---|
1286 | wd.damage/= wflag; |
---|
1287 | else |
---|
1288 | ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); |
---|
1289 | } |
---|
1290 | |
---|
1291 | //Add any bonuses that modify the base baseatk+watk (pre-skills) |
---|
1292 | if(sd) |
---|
1293 | { |
---|
1294 | if (sd->atk_rate != 100) |
---|
1295 | ATK_RATE(sd->atk_rate); |
---|
1296 | |
---|
1297 | if(flag.cri && sd->crit_atk_rate) |
---|
1298 | ATK_ADDRATE(sd->crit_atk_rate); |
---|
1299 | |
---|
1300 | if(sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0){ |
---|
1301 | i = party_foreachsamemap(party_sub_count, sd, 0); |
---|
1302 | ATK_ADDRATE(2*skill*i); |
---|
1303 | } |
---|
1304 | } |
---|
1305 | break; |
---|
1306 | } //End default case |
---|
1307 | } //End switch(skill_num) |
---|
1308 | |
---|
1309 | //Skill damage modifiers that stack linearly |
---|
1310 | if(sc && skill_num != PA_SACRIFICE) |
---|
1311 | { |
---|
1312 | if(sc->data[SC_OVERTHRUST]) |
---|
1313 | skillratio += sc->data[SC_OVERTHRUST]->val3; |
---|
1314 | if(sc->data[SC_MAXOVERTHRUST]) |
---|
1315 | skillratio += sc->data[SC_MAXOVERTHRUST]->val2; |
---|
1316 | if(sc->data[SC_BERSERK]) |
---|
1317 | skillratio += 100; |
---|
1318 | } |
---|
1319 | if (!skill_num) |
---|
1320 | { |
---|
1321 | // Random chance to deal multiplied damage - Consider it as part of skill-based-damage |
---|
1322 | if(sd && |
---|
1323 | sd->random_attack_increase_add > 0 && |
---|
1324 | sd->random_attack_increase_per && |
---|
1325 | rand()%100 < sd->random_attack_increase_per |
---|
1326 | ) |
---|
1327 | skillratio += sd->random_attack_increase_add; |
---|
1328 | |
---|
1329 | ATK_RATE(skillratio); |
---|
1330 | } else { //Skills |
---|
1331 | switch( skill_num ) |
---|
1332 | { |
---|
1333 | //Begin Custom Job (blackmagic) |
---|
1334 | case NC_DEATHHAND: // Necro Death Hand [Brain] |
---|
1335 | skillratio += -25+25*skill_lv; |
---|
1336 | break; |
---|
1337 | //End Black Magic Custom Jobs |
---|
1338 | case SM_BASH: |
---|
1339 | skillratio += 30*skill_lv; |
---|
1340 | break; |
---|
1341 | case SM_MAGNUM: |
---|
1342 | skillratio += 20*skill_lv; |
---|
1343 | break; |
---|
1344 | case MC_MAMMONITE: |
---|
1345 | skillratio += 50*skill_lv; |
---|
1346 | break; |
---|
1347 | case HT_POWER: //FIXME: How exactly is the STR based damage supposed to be done? [Skotlex] |
---|
1348 | skillratio += 5*sstatus->str; |
---|
1349 | break; |
---|
1350 | case AC_DOUBLE: |
---|
1351 | skillratio += 10*(skill_lv-1); |
---|
1352 | break; |
---|
1353 | case AC_SHOWER: |
---|
1354 | skillratio += 5*skill_lv-25; |
---|
1355 | break; |
---|
1356 | case AC_CHARGEARROW: |
---|
1357 | skillratio += 50; |
---|
1358 | break; |
---|
1359 | case HT_FREEZINGTRAP: |
---|
1360 | skillratio += -50+10*skill_lv; |
---|
1361 | break; |
---|
1362 | case KN_PIERCE: |
---|
1363 | skillratio += 10*skill_lv; |
---|
1364 | break; |
---|
1365 | case KN_SPEARSTAB: |
---|
1366 | skillratio += 15*skill_lv; |
---|
1367 | break; |
---|
1368 | case KN_SPEARBOOMERANG: |
---|
1369 | skillratio += 50*skill_lv; |
---|
1370 | break; |
---|
1371 | case KN_BRANDISHSPEAR: |
---|
1372 | { |
---|
1373 | int ratio = 100+20*skill_lv; |
---|
1374 | skillratio += ratio-100; |
---|
1375 | if(skill_lv>3 && wflag==1) skillratio += ratio/2; |
---|
1376 | if(skill_lv>6 && wflag==1) skillratio += ratio/4; |
---|
1377 | if(skill_lv>9 && wflag==1) skillratio += ratio/8; |
---|
1378 | if(skill_lv>6 && wflag==2) skillratio += ratio/2; |
---|
1379 | if(skill_lv>9 && wflag==2) skillratio += ratio/4; |
---|
1380 | if(skill_lv>9 && wflag==3) skillratio += ratio/2; |
---|
1381 | break; |
---|
1382 | } |
---|
1383 | case KN_BOWLINGBASH: |
---|
1384 | skillratio+= 40*skill_lv; |
---|
1385 | break; |
---|
1386 | case AS_GRIMTOOTH: |
---|
1387 | skillratio += 20*skill_lv; |
---|
1388 | break; |
---|
1389 | case AS_POISONREACT: |
---|
1390 | skillratio += 30*skill_lv; |
---|
1391 | break; |
---|
1392 | case AS_SONICBLOW: |
---|
1393 | skillratio += -50+5*skill_lv; |
---|
1394 | break; |
---|
1395 | case TF_SPRINKLESAND: |
---|
1396 | skillratio += 30; |
---|
1397 | break; |
---|
1398 | case MC_CARTREVOLUTION: |
---|
1399 | skillratio += 50; |
---|
1400 | if(sd && sd->cart_weight) |
---|
1401 | skillratio += 100*sd->cart_weight/battle_config.max_cart_weight; // +1% every 1% weight |
---|
1402 | else if (!sd) |
---|
1403 | skillratio += 100; //Max damage for non players. |
---|
1404 | break; |
---|
1405 | case NPC_RANDOMATTACK: |
---|
1406 | skillratio += rand()%150-50; |
---|
1407 | break; |
---|
1408 | case NPC_WATERATTACK: |
---|
1409 | case NPC_GROUNDATTACK: |
---|
1410 | case NPC_FIREATTACK: |
---|
1411 | case NPC_WINDATTACK: |
---|
1412 | case NPC_POISONATTACK: |
---|
1413 | case NPC_HOLYATTACK: |
---|
1414 | case NPC_DARKNESSATTACK: |
---|
1415 | case NPC_UNDEADATTACK: |
---|
1416 | case NPC_TELEKINESISATTACK: |
---|
1417 | case NPC_BLOODDRAIN: |
---|
1418 | case NPC_ACIDBREATH: |
---|
1419 | case NPC_DARKNESSBREATH: |
---|
1420 | case NPC_FIREBREATH: |
---|
1421 | case NPC_ICEBREATH: |
---|
1422 | case NPC_THUNDERBREATH: |
---|
1423 | case NPC_HELLJUDGEMENT: |
---|
1424 | case NPC_PULSESTRIKE: |
---|
1425 | skillratio += 100*(skill_lv-1); |
---|
1426 | break; |
---|
1427 | case RG_BACKSTAP: |
---|
1428 | if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty) |
---|
1429 | skillratio += (200+40*skill_lv)/2; |
---|
1430 | else |
---|
1431 | skillratio += 200+40*skill_lv; |
---|
1432 | break; |
---|
1433 | case RG_RAID: |
---|
1434 | skillratio += 40*skill_lv; |
---|
1435 | break; |
---|
1436 | case RG_INTIMIDATE: |
---|
1437 | skillratio += 30*skill_lv; |
---|
1438 | break; |
---|
1439 | case CR_SHIELDCHARGE: |
---|
1440 | skillratio += 20*skill_lv; |
---|
1441 | break; |
---|
1442 | case CR_SHIELDBOOMERANG: |
---|
1443 | skillratio += 30*skill_lv; |
---|
1444 | break; |
---|
1445 | case NPC_DARKCROSS: |
---|
1446 | case CR_HOLYCROSS: |
---|
1447 | skillratio += 35*skill_lv; |
---|
1448 | break; |
---|
1449 | case AM_DEMONSTRATION: |
---|
1450 | skillratio += 20*skill_lv; |
---|
1451 | break; |
---|
1452 | case AM_ACIDTERROR: |
---|
1453 | skillratio += 40*skill_lv; |
---|
1454 | break; |
---|
1455 | case MO_FINGEROFFENSIVE: |
---|
1456 | skillratio+= 50 * skill_lv; |
---|
1457 | break; |
---|
1458 | case MO_INVESTIGATE: |
---|
1459 | skillratio += 75*skill_lv; |
---|
1460 | flag.pdef = flag.pdef2 = 2; |
---|
1461 | break; |
---|
1462 | case MO_EXTREMITYFIST: |
---|
1463 | { //Overflow check. [Skotlex] |
---|
1464 | unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10); |
---|
1465 | //You'd need something like 6K SP to reach this max, so should be fine for most purposes. |
---|
1466 | if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased. |
---|
1467 | skillratio = (unsigned short)ratio; |
---|
1468 | status_set_sp(src, 0, 0); |
---|
1469 | } |
---|
1470 | break; |
---|
1471 | case MO_TRIPLEATTACK: |
---|
1472 | skillratio += 20*skill_lv; |
---|
1473 | break; |
---|
1474 | case MO_CHAINCOMBO: |
---|
1475 | skillratio += 50+50*skill_lv; |
---|
1476 | break; |
---|
1477 | case MO_COMBOFINISH: |
---|
1478 | skillratio += 140+60*skill_lv; |
---|
1479 | break; |
---|
1480 | case BA_MUSICALSTRIKE: |
---|
1481 | case DC_THROWARROW: |
---|
1482 | skillratio += 25+25*skill_lv; |
---|
1483 | break; |
---|
1484 | case CH_TIGERFIST: |
---|
1485 | skillratio += 100*skill_lv-60; |
---|
1486 | break; |
---|
1487 | case CH_CHAINCRUSH: |
---|
1488 | skillratio += 300+100*skill_lv; |
---|
1489 | break; |
---|
1490 | case CH_PALMSTRIKE: |
---|
1491 | skillratio += 100+100*skill_lv; |
---|
1492 | break; |
---|
1493 | case LK_HEADCRUSH: |
---|
1494 | skillratio += 40*skill_lv; |
---|
1495 | break; |
---|
1496 | case LK_JOINTBEAT: |
---|
1497 | i = 10*skill_lv-50; |
---|
1498 | // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. |
---|
1499 | if (wflag&BREAK_NECK) i*=2; |
---|
1500 | skillratio += i; |
---|
1501 | break; |
---|
1502 | case ASC_METEORASSAULT: |
---|
1503 | skillratio += 40*skill_lv-60; |
---|
1504 | break; |
---|
1505 | case SN_SHARPSHOOTING: |
---|
1506 | skillratio += 100+50*skill_lv; |
---|
1507 | break; |
---|
1508 | case CG_ARROWVULCAN: |
---|
1509 | skillratio += 100+100*skill_lv; |
---|
1510 | break; |
---|
1511 | case AS_SPLASHER: |
---|
1512 | skillratio += 400+50*skill_lv; |
---|
1513 | if(sd) |
---|
1514 | skillratio += 30 * pc_checkskill(sd,AS_POISONREACT); |
---|
1515 | break; |
---|
1516 | case ASC_BREAKER: |
---|
1517 | skillratio += 100*skill_lv-100; |
---|
1518 | break; |
---|
1519 | case PA_SACRIFICE: |
---|
1520 | skillratio += 10*skill_lv-10; |
---|
1521 | break; |
---|
1522 | case PA_SHIELDCHAIN: |
---|
1523 | skillratio += 30*skill_lv; |
---|
1524 | break; |
---|
1525 | case WS_CARTTERMINATION: |
---|
1526 | i = 10 * (16 - skill_lv); |
---|
1527 | if (i < 1) i = 1; |
---|
1528 | //Preserve damage ratio when max cart weight is changed. |
---|
1529 | if(sd && sd->cart_weight) |
---|
1530 | skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100; |
---|
1531 | else if (!sd) |
---|
1532 | skillratio += 80000 / i - 100; |
---|
1533 | break; |
---|
1534 | case TK_DOWNKICK: |
---|
1535 | skillratio += 60 + 20*skill_lv; |
---|
1536 | break; |
---|
1537 | case TK_STORMKICK: |
---|
1538 | skillratio += 60 + 20*skill_lv; |
---|
1539 | break; |
---|
1540 | case TK_TURNKICK: |
---|
1541 | skillratio += 90 + 30*skill_lv; |
---|
1542 | break; |
---|
1543 | case TK_COUNTER: |
---|
1544 | skillratio += 90 + 30*skill_lv; |
---|
1545 | break; |
---|
1546 | case TK_JUMPKICK: |
---|
1547 | skillratio += -70 + 10*skill_lv; |
---|
1548 | if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num) |
---|
1549 | skillratio += 10*status_get_lv(src)/3; //Tumble bonus |
---|
1550 | if (wflag) |
---|
1551 | skillratio += 10*status_get_lv(src)/3; //Running bonus (TODO: What is the real bonus?) |
---|
1552 | break; |
---|
1553 | case GS_TRIPLEACTION: |
---|
1554 | skillratio += 50*skill_lv; |
---|
1555 | break; |
---|
1556 | case GS_BULLSEYE: |
---|
1557 | //Only works well against brute/demihumans non bosses. |
---|
1558 | if((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) |
---|
1559 | && !(tstatus->mode&MD_BOSS)) |
---|
1560 | skillratio += 400; |
---|
1561 | break; |
---|
1562 | case GS_TRACKING: |
---|
1563 | skillratio += 100 *(skill_lv+1); |
---|
1564 | break; |
---|
1565 | case GS_PIERCINGSHOT: |
---|
1566 | skillratio += 20*skill_lv; |
---|
1567 | break; |
---|
1568 | case GS_RAPIDSHOWER: |
---|
1569 | skillratio += 10*skill_lv; |
---|
1570 | break; |
---|
1571 | case GS_DESPERADO: |
---|
1572 | skillratio += 50*(skill_lv-1); |
---|
1573 | break; |
---|
1574 | case GS_DUST: |
---|
1575 | skillratio += 50*skill_lv; |
---|
1576 | break; |
---|
1577 | case GS_FULLBUSTER: |
---|
1578 | skillratio += 100*(skill_lv+2); |
---|
1579 | break; |
---|
1580 | case GS_SPREADATTACK: |
---|
1581 | skillratio += 20*(skill_lv-1); |
---|
1582 | break; |
---|
1583 | case NJ_HUUMA: |
---|
1584 | skillratio += 50 + 150*skill_lv; |
---|
1585 | break; |
---|
1586 | case NJ_TATAMIGAESHI: |
---|
1587 | skillratio += 10*skill_lv; |
---|
1588 | break; |
---|
1589 | case NJ_KASUMIKIRI: |
---|
1590 | skillratio += 10*skill_lv; |
---|
1591 | break; |
---|
1592 | case NJ_KIRIKAGE: |
---|
1593 | skillratio += 100*(skill_lv-1); |
---|
1594 | break; |
---|
1595 | case KN_CHARGEATK: |
---|
1596 | { |
---|
1597 | int k = (wflag-1)/3; //+100% every 3 cells of distance |
---|
1598 | if( k > 2 ) k = 2; // ...but hard-limited to 300%. |
---|
1599 | skillratio += 100 * k; |
---|
1600 | } |
---|
1601 | break; |
---|
1602 | case HT_PHANTASMIC: |
---|
1603 | skillratio += 50; |
---|
1604 | break; |
---|
1605 | case MO_BALKYOUNG: |
---|
1606 | skillratio += 200; |
---|
1607 | break; |
---|
1608 | case HFLI_MOON: //[orn] |
---|
1609 | skillratio += 10+110*skill_lv; |
---|
1610 | break; |
---|
1611 | case HFLI_SBR44: //[orn] |
---|
1612 | skillratio += 100 *(skill_lv-1); |
---|
1613 | break; |
---|
1614 | //Begin Custom Jobs (blackmagic) |
---|
1615 | //Mercenary Skills [Brainstorm] |
---|
1616 | case MS_BASH: |
---|
1617 | skillratio += 30*skill_lv; |
---|
1618 | break; |
---|
1619 | case MER_CRASH: |
---|
1620 | skillratio += 10*skill_lv; |
---|
1621 | break; |
---|
1622 | //end custom jobs |
---|
1623 | } |
---|
1624 | |
---|
1625 | ATK_RATE(skillratio); |
---|
1626 | |
---|
1627 | //Constant/misc additions from skills |
---|
1628 | switch (skill_num) { |
---|
1629 | case MO_EXTREMITYFIST: |
---|
1630 | ATK_ADD(250 + 150*skill_lv); |
---|
1631 | break; |
---|
1632 | case TK_DOWNKICK: |
---|
1633 | case TK_STORMKICK: |
---|
1634 | case TK_TURNKICK: |
---|
1635 | case TK_COUNTER: |
---|
1636 | case TK_JUMPKICK: |
---|
1637 | //TK_RUN kick damage bonus. |
---|
1638 | if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) |
---|
1639 | ATK_ADD(10*pc_checkskill(sd, TK_RUN)); |
---|
1640 | break; |
---|
1641 | case GS_MAGICALBULLET: |
---|
1642 | if(sstatus->matk_max>sstatus->matk_min) { |
---|
1643 | ATK_ADD(sstatus->matk_min+rand()%(sstatus->matk_max-sstatus->matk_min)); |
---|
1644 | } else { |
---|
1645 | ATK_ADD(sstatus->matk_min); |
---|
1646 | } |
---|
1647 | break; |
---|
1648 | case NJ_SYURIKEN: |
---|
1649 | ATK_ADD(4*skill_lv); |
---|
1650 | break; |
---|
1651 | } |
---|
1652 | } |
---|
1653 | //Div fix. |
---|
1654 | damage_div_fix(wd.damage, wd.div_); |
---|
1655 | |
---|
1656 | //The following are applied on top of current damage and are stackable. |
---|
1657 | if (sc) { |
---|
1658 | if(sc->data[SC_TRUESIGHT]) |
---|
1659 | ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); |
---|
1660 | |
---|
1661 | if(sc->data[SC_EDP] && |
---|
1662 | skill_num != ASC_BREAKER && |
---|
1663 | skill_num != ASC_METEORASSAULT && |
---|
1664 | skill_num != AS_SPLASHER && |
---|
1665 | skill_num != AS_VENOMKNIFE) |
---|
1666 | ATK_ADDRATE(sc->data[SC_EDP]->val3); |
---|
1667 | } |
---|
1668 | |
---|
1669 | switch (skill_num) { |
---|
1670 | case AS_SONICBLOW: |
---|
1671 | if (sc && sc->data[SC_SPIRIT] && |
---|
1672 | sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) |
---|
1673 | ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe |
---|
1674 | |
---|
1675 | if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) |
---|
1676 | ATK_ADDRATE(10); |
---|
1677 | break; |
---|
1678 | case CR_SHIELDBOOMERANG: |
---|
1679 | if(sc && sc->data[SC_SPIRIT] && |
---|
1680 | sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) |
---|
1681 | ATK_ADDRATE(100); |
---|
1682 | break; |
---|
1683 | } |
---|
1684 | |
---|
1685 | if(sd) |
---|
1686 | { |
---|
1687 | if (skill_num && (i = pc_skillatk_bonus(sd, skill_num))) |
---|
1688 | ATK_ADDRATE(i); |
---|
1689 | |
---|
1690 | if(skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && |
---|
1691 | skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && |
---|
1692 | skill_num != PA_SHIELDCHAIN |
---|
1693 | && !flag.cri) |
---|
1694 | { //Elemental/Racial adjustments |
---|
1695 | if(sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || |
---|
1696 | sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) || |
---|
1697 | sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) |
---|
1698 | ) |
---|
1699 | flag.pdef = 1; |
---|
1700 | |
---|
1701 | if(sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || |
---|
1702 | sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) || |
---|
1703 | sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) |
---|
1704 | ) { //Pass effect onto right hand if configured so. [Skotlex] |
---|
1705 | if (battle_config.left_cardfix_to_right && flag.rh) |
---|
1706 | flag.pdef = 1; |
---|
1707 | else |
---|
1708 | flag.pdef2 = 1; |
---|
1709 | } |
---|
1710 | } |
---|
1711 | |
---|
1712 | if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS) |
---|
1713 | { //Ignore Defense? |
---|
1714 | if (!flag.idef && ( |
---|
1715 | sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) || |
---|
1716 | sd->right_weapon.ignore_def_race & (1<<tstatus->race) || |
---|
1717 | sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) |
---|
1718 | )) |
---|
1719 | flag.idef = 1; |
---|
1720 | |
---|
1721 | if (!flag.idef2 && ( |
---|
1722 | sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) || |
---|
1723 | sd->left_weapon.ignore_def_race & (1<<tstatus->race) || |
---|
1724 | sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) |
---|
1725 | )) { |
---|
1726 | if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex] |
---|
1727 | flag.idef = 1; |
---|
1728 | else |
---|
1729 | flag.idef2 = 1; |
---|
1730 | } |
---|
1731 | } |
---|
1732 | } |
---|
1733 | |
---|
1734 | if (!flag.idef || !flag.idef2) |
---|
1735 | { //Defense reduction |
---|
1736 | short vit_def; |
---|
1737 | signed char def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. |
---|
1738 | short def2 = (short)tstatus->def2; |
---|
1739 | if(battle_config.vit_penalty_type && |
---|
1740 | battle_config.vit_penalty_target&target->type) |
---|
1741 | { |
---|
1742 | unsigned char target_count; //256 max targets should be a sane max |
---|
1743 | target_count = unit_counttargeted(target,battle_config.vit_penalty_count_lv); |
---|
1744 | if(target_count >= battle_config.vit_penalty_count) { |
---|
1745 | if(battle_config.vit_penalty_type == 1) { |
---|
1746 | def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; |
---|
1747 | def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; |
---|
1748 | } else { //Assume type 2 |
---|
1749 | def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; |
---|
1750 | def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; |
---|
1751 | } |
---|
1752 | } |
---|
1753 | if(skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] |
---|
1754 | if(def2 < 1) def2 = 1; |
---|
1755 | } |
---|
1756 | //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def |
---|
1757 | if (tsd) //Sd vit-eq |
---|
1758 | { //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) |
---|
1759 | vit_def = def2*(def2-15)/150; |
---|
1760 | vit_def = def2/2 + (vit_def>0?rand()%vit_def:0); |
---|
1761 | |
---|
1762 | if((sstatus->race==RC_UNDEAD || sstatus->race==RC_DEMON) && |
---|
1763 | src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0) |
---|
1764 | vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn |
---|
1765 | } else { //Mob-Pet vit-eq |
---|
1766 | //VIT + rnd(0,[VIT/20]^2-1) |
---|
1767 | vit_def = (def2/20)*(def2/20); |
---|
1768 | vit_def = def2 + (vit_def>0?rand()%vit_def:0); |
---|
1769 | } |
---|
1770 | |
---|
1771 | if (battle_config.weapon_defense_type) { |
---|
1772 | vit_def += def1*battle_config.weapon_defense_type; |
---|
1773 | def1 = 0; |
---|
1774 | } |
---|
1775 | if (def1 > 100) def1 = 100; |
---|
1776 | ATK_RATE2( |
---|
1777 | flag.idef ?100: |
---|
1778 | (flag.pdef ?flag.pdef *(def1 + vit_def): |
---|
1779 | 100-def1), |
---|
1780 | flag.idef2?100: |
---|
1781 | (flag.pdef2?flag.pdef2*(def1 + vit_def): |
---|
1782 | 100-def1) |
---|
1783 | ); |
---|
1784 | ATK_ADD2( |
---|
1785 | flag.idef ||flag.pdef ?0:-vit_def, |
---|
1786 | flag.idef2||flag.pdef2?0:-vit_def |
---|
1787 | ); |
---|
1788 | } |
---|
1789 | |
---|
1790 | //Post skill/vit reduction damage increases |
---|
1791 | if (sc && skill_num != LK_SPIRALPIERCE) |
---|
1792 | { //SC skill damages |
---|
1793 | if(sc->data[SC_AURABLADE]) |
---|
1794 | ATK_ADD(20*sc->data[SC_AURABLADE]->val1); |
---|
1795 | } |
---|
1796 | |
---|
1797 | //Refine bonus |
---|
1798 | if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) { |
---|
1799 | if (skill_num == MO_FINGEROFFENSIVE) //Counts refine bonus multiple times |
---|
1800 | { |
---|
1801 | ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2); |
---|
1802 | } else { |
---|
1803 | ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2); |
---|
1804 | } |
---|
1805 | } |
---|
1806 | |
---|
1807 | //Set to min of 1 |
---|
1808 | if (flag.rh && wd.damage < 1) wd.damage = 1; |
---|
1809 | if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; |
---|
1810 | |
---|
1811 | if (sd && flag.weapon && |
---|
1812 | skill_num != MO_INVESTIGATE && |
---|
1813 | skill_num != MO_EXTREMITYFIST && |
---|
1814 | skill_num != CR_GRANDCROSS) |
---|
1815 | { //Add mastery damage |
---|
1816 | if(skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR && |
---|
1817 | (skill=pc_checkskill(sd,ASC_KATAR)) > 0) |
---|
1818 | { //Adv Katar Mastery is does not applies to ASC_BREAKER, |
---|
1819 | // but other masteries DO apply >_> |
---|
1820 | ATK_ADDRATE(10+ 2*skill); |
---|
1821 | } |
---|
1822 | |
---|
1823 | wd.damage = battle_addmastery(sd,target,wd.damage,0); |
---|
1824 | if (flag.lh) |
---|
1825 | wd.damage2 = battle_addmastery(sd,target,wd.damage2,1); |
---|
1826 | |
---|
1827 | if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger |
---|
1828 | else |
---|
1829 | ARR_FIND(0, 3, i, t_class == sd->hate_mob[i]); |
---|
1830 | if (i < 3 && (skill=pc_checkskill(sd,sg_info[i].anger_id))) |
---|
1831 | { |
---|
1832 | skillratio = sd->status.base_level + sstatus->dex + sstatus->luk; |
---|
1833 | if (i == 2) skillratio += sstatus->str; //Star Anger |
---|
1834 | if (skill<4) |
---|
1835 | skillratio /= 12-3*skill; |
---|
1836 | ATK_ADDRATE(skillratio); |
---|
1837 | } |
---|
1838 | if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) |
---|
1839 | ATK_ADD(3*skill); |
---|
1840 | if (skill_num == NJ_KUNAI) |
---|
1841 | ATK_ADD(60); |
---|
1842 | } |
---|
1843 | } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks |
---|
1844 | else if(wd.div_ < 0) //Since the attack missed... |
---|
1845 | wd.div_ *= -1; |
---|
1846 | |
---|
1847 | if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) |
---|
1848 | return wd; //Enough, rest is not needed. |
---|
1849 | |
---|
1850 | if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) |
---|
1851 | ATK_ADD(skill*2); |
---|
1852 | |
---|
1853 | if(skill_num==TF_POISON) |
---|
1854 | ATK_ADD(15*skill_lv); |
---|
1855 | |
---|
1856 | if(!(nk&NK_NO_ELEFIX || (s_ele == ELE_NEUTRAL && |
---|
1857 | battle_config.attack_attr_none&src->type))) |
---|
1858 | { //Elemental attribute fix |
---|
1859 | if (wd.damage > 0) |
---|
1860 | { |
---|
1861 | wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); |
---|
1862 | if(skill_num==MC_CARTREVOLUTION) //Cart Revolution applies the element fix once more with neutral element |
---|
1863 | wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); |
---|
1864 | if(skill_num== GS_GROUNDDRIFT) //Additional 50*lv Neutral damage. |
---|
1865 | wd.damage+= battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); |
---|
1866 | } |
---|
1867 | if (flag.lh && wd.damage2 > 0) |
---|
1868 | wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); |
---|
1869 | if(sc && sc->data[SC_WATK_ELEMENT]) |
---|
1870 | { //Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] |
---|
1871 | int damage= battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)); |
---|
1872 | damage = damage*sc->data[SC_WATK_ELEMENT]->val2/100; |
---|
1873 | damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT]->val1,tstatus->def_ele, tstatus->ele_lv); |
---|
1874 | ATK_ADD(damage); |
---|
1875 | } |
---|
1876 | } |
---|
1877 | |
---|
1878 | if (sd) |
---|
1879 | { |
---|
1880 | if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. |
---|
1881 | ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); |
---|
1882 | if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] |
---|
1883 | ATK_ADD(wd.div_*sd->spiritball_old*3); |
---|
1884 | } else { |
---|
1885 | ATK_ADD(wd.div_*sd->spiritball*3); |
---|
1886 | } |
---|
1887 | |
---|
1888 | //Card Fix, sd side |
---|
1889 | if ((wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK)) |
---|
1890 | { |
---|
1891 | int cardfix = 1000, cardfix_ = 1000; |
---|
1892 | int t_race2 = status_get_race2(target); |
---|
1893 | if(sd->state.arrow_atk) |
---|
1894 | { |
---|
1895 | cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; |
---|
1896 | if (!(nk&NK_NO_ELEFIX)) |
---|
1897 | cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->arrow_addele[tstatus->def_ele])/100; |
---|
1898 | cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; |
---|
1899 | cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; |
---|
1900 | cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; |
---|
1901 | } else { //Melee attack |
---|
1902 | if(!battle_config.left_cardfix_to_right) |
---|
1903 | { |
---|
1904 | cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; |
---|
1905 | if (!(nk&NK_NO_ELEFIX)) |
---|
1906 | cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele])/100; |
---|
1907 | cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; |
---|
1908 | cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; |
---|
1909 | cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; |
---|
1910 | |
---|
1911 | if (flag.lh) |
---|
1912 | { |
---|
1913 | cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; |
---|
1914 | if (!(nk&NK_NO_ELEFIX)) |
---|
1915 | cardfix_=cardfix_*(100+sd->left_weapon.addele[tstatus->def_ele])/100; |
---|
1916 | cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; |
---|
1917 | cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; |
---|
1918 | cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; |
---|
1919 | } |
---|
1920 | } else { |
---|
1921 | cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; |
---|
1922 | cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->left_weapon.addele[tstatus->def_ele])/100; |
---|
1923 | cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; |
---|
1924 | cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; |
---|
1925 | cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; |
---|
1926 | } |
---|
1927 | } |
---|
1928 | |
---|
1929 | for(i=0;i<ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate;i++) { |
---|
1930 | if(sd->right_weapon.add_dmg[i].class_ == t_class) { |
---|
1931 | cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; |
---|
1932 | break; |
---|
1933 | } |
---|
1934 | } |
---|
1935 | |
---|
1936 | if (flag.lh) |
---|
1937 | { |
---|
1938 | for(i=0;i<ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate;i++) { |
---|
1939 | if(sd->left_weapon.add_dmg[i].class_ == t_class) { |
---|
1940 | cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; |
---|
1941 | break; |
---|
1942 | } |
---|
1943 | } |
---|
1944 | } |
---|
1945 | |
---|
1946 | if(wd.flag&BF_LONG) |
---|
1947 | cardfix=cardfix*(100+sd->long_attack_atk_rate)/100; |
---|
1948 | |
---|
1949 | if (cardfix != 1000 || cardfix_ != 1000) |
---|
1950 | ATK_RATE2(cardfix/10, cardfix_/10); //What happens if you use right-to-left and there's no right weapon, only left? |
---|
1951 | } |
---|
1952 | |
---|
1953 | if (skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN) { //Refine bonus applies after cards and elements. |
---|
1954 | short index= sd->equip_index[EQI_HAND_L]; |
---|
1955 | if (index >= 0 && |
---|
1956 | sd->inventory_data[index] && |
---|
1957 | sd->inventory_data[index]->type == IT_ARMOR) |
---|
1958 | ATK_ADD(10*sd->status.inventory[index].refine); |
---|
1959 | } |
---|
1960 | } //if (sd) |
---|
1961 | |
---|
1962 | //Card Fix, tsd sid |
---|
1963 | if (tsd && !(nk&NK_NO_CARDFIX_DEF)) |
---|
1964 | { |
---|
1965 | short s_race2,s_class; |
---|
1966 | short cardfix=1000; |
---|
1967 | |
---|
1968 | s_race2 = status_get_race2(src); |
---|
1969 | s_class = status_get_class(src); |
---|
1970 | |
---|
1971 | if (!(nk&NK_NO_ELEFIX)) |
---|
1972 | { |
---|
1973 | cardfix=cardfix*(100-tsd->subele[s_ele])/100; |
---|
1974 | if (flag.lh && s_ele_ != s_ele) |
---|
1975 | cardfix=cardfix*(100-tsd->subele[s_ele_])/100; |
---|
1976 | } |
---|
1977 | cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; |
---|
1978 | cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; |
---|
1979 | cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; |
---|
1980 | cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; |
---|
1981 | for(i=0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++) { |
---|
1982 | if(tsd->add_def[i].class_ == s_class) { |
---|
1983 | cardfix=cardfix*(100-tsd->add_def[i].rate)/100; |
---|
1984 | break; |
---|
1985 | } |
---|
1986 | } |
---|
1987 | |
---|
1988 | if(wd.flag&BF_SHORT) |
---|
1989 | cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; |
---|
1990 | else // BF_LONG (there's no other choice) |
---|
1991 | cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; |
---|
1992 | |
---|
1993 | if( tsd->sc.data[SC_DEF_RATE] ) |
---|
1994 | cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100; |
---|
1995 | |
---|
1996 | if (cardfix != 1000) |
---|
1997 | ATK_RATE(cardfix/10); |
---|
1998 | } |
---|
1999 | |
---|
2000 | if(flag.infdef) |
---|
2001 | { //Plants receive 1 damage when hit |
---|
2002 | if (flag.rh && (flag.hit || wd.damage>0)) |
---|
2003 | wd.damage = 1; |
---|
2004 | if (flag.lh && (flag.hit || wd.damage2>0)) |
---|
2005 | wd.damage2 = 1; |
---|
2006 | if (!(battle_config.skill_min_damage&1)) |
---|
2007 | //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] |
---|
2008 | return wd; |
---|
2009 | } |
---|
2010 | |
---|
2011 | if(sd && !skill_num && !flag.cri) |
---|
2012 | { //Check for double attack. |
---|
2013 | if(((skill_lv = pc_checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER) |
---|
2014 | ||(sd->double_rate > 0 && sd->weapontype1 != W_FIST)) //Will fail bare-handed |
---|
2015 | { //Success chance is not added, the higher one is used [Skotlex] |
---|
2016 | if (rand()%100 < (5*skill_lv>sd->double_rate?5*skill_lv:sd->double_rate)) |
---|
2017 | { |
---|
2018 | wd.div_=skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1); |
---|
2019 | damage_div_fix(wd.damage, wd.div_); |
---|
2020 | wd.type = 0x08; |
---|
2021 | } |
---|
2022 | } else |
---|
2023 | if (sd->weapontype1 == W_REVOLVER && |
---|
2024 | (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && |
---|
2025 | (rand()%100 < 5*skill_lv) |
---|
2026 | ) |
---|
2027 | { |
---|
2028 | wd.div_=skill_get_num(GS_CHAINACTION,skill_lv); |
---|
2029 | damage_div_fix(wd.damage, wd.div_); |
---|
2030 | wd.type = 0x08; |
---|
2031 | } |
---|
2032 | } |
---|
2033 | |
---|
2034 | if (sd) |
---|
2035 | { |
---|
2036 | if (!flag.rh && flag.lh) |
---|
2037 | { //Move lh damage to the rh |
---|
2038 | wd.damage = wd.damage2; |
---|
2039 | wd.damage2 = 0; |
---|
2040 | flag.rh=1; |
---|
2041 | flag.lh=0; |
---|
2042 | } else if(flag.rh && flag.lh) |
---|
2043 | { //Dual-wield |
---|
2044 | if (wd.damage) |
---|
2045 | { |
---|
2046 | skill = pc_checkskill(sd,AS_RIGHT); |
---|
2047 | wd.damage = wd.damage * (50 + (skill * 10))/100; |
---|
2048 | if(wd.damage < 1) wd.damage = 1; |
---|
2049 | } |
---|
2050 | if (wd.damage2) |
---|
2051 | { |
---|
2052 | skill = pc_checkskill(sd,AS_LEFT); |
---|
2053 | wd.damage2 = wd.damage2 * (30 + (skill * 10))/100; |
---|
2054 | if(wd.damage2 < 1) wd.damage2 = 1; |
---|
2055 | } |
---|
2056 | } else if(sd->status.weapon == W_KATAR && !skill_num) |
---|
2057 | { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) |
---|
2058 | skill = pc_checkskill(sd,TF_DOUBLE); |
---|
2059 | wd.damage2 = wd.damage * (1 + (skill * 2))/100; |
---|
2060 | |
---|
2061 | if(wd.damage && !wd.damage2) wd.damage2 = 1; |
---|
2062 | flag.lh = 1; |
---|
2063 | } |
---|
2064 | } |
---|
2065 | |
---|
2066 | if(!flag.rh && wd.damage) |
---|
2067 | wd.damage=0; |
---|
2068 | |
---|
2069 | if(!flag.lh && wd.damage2) |
---|
2070 | wd.damage2=0; |
---|
2071 | |
---|
2072 | if(wd.damage + wd.damage2) |
---|
2073 | { //There is a total damage value |
---|
2074 | if(!wd.damage2) { |
---|
2075 | wd.damage=battle_calc_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2076 | if (map_flag_gvg2(target->m)) |
---|
2077 | wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2078 | } else |
---|
2079 | if(!wd.damage) { |
---|
2080 | wd.damage2=battle_calc_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2081 | if (map_flag_gvg2(target->m)) |
---|
2082 | wd.damage2=battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2083 | } else |
---|
2084 | { |
---|
2085 | int d1=wd.damage+wd.damage2,d2=wd.damage2; |
---|
2086 | wd.damage=battle_calc_damage(src,target,d1,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2087 | if (map_flag_gvg2(target->m)) |
---|
2088 | wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); |
---|
2089 | wd.damage2=(d2*100/d1)*wd.damage/100; |
---|
2090 | if(wd.damage > 1 && wd.damage2 < 1) wd.damage2=1; |
---|
2091 | wd.damage-=wd.damage2; |
---|
2092 | } |
---|
2093 | } |
---|
2094 | |
---|
2095 | if(skill_num==ASC_BREAKER) |
---|
2096 | { //Breaker's int-based damage (a misc attack?) |
---|
2097 | struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag); |
---|
2098 | wd.damage += md.damage; |
---|
2099 | } |
---|
2100 | |
---|
2101 | if (wd.damage || wd.damage2) { |
---|
2102 | if (sd && battle_config.equip_self_break_rate) |
---|
2103 | { // Self weapon breaking |
---|
2104 | int breakrate = battle_config.equip_natural_break_rate; |
---|
2105 | if (sc) { |
---|
2106 | if(sc->data[SC_OVERTHRUST]) |
---|
2107 | breakrate += 10; |
---|
2108 | if(sc->data[SC_MAXOVERTHRUST]) |
---|
2109 | breakrate += 10; |
---|
2110 | } |
---|
2111 | if (breakrate) |
---|
2112 | skill_break_equip(src, EQP_WEAPON, breakrate, BCT_SELF); |
---|
2113 | } |
---|
2114 | //Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity. |
---|
2115 | if (battle_config.equip_skill_break_rate && skill_num != WS_CARTTERMINATION && skill_num != ITM_TOMAHAWK) |
---|
2116 | { // Target equipment breaking |
---|
2117 | int breakrate[2] = {0,0}; // weapon = 0, armor = 1 |
---|
2118 | if (sd) { // Break rate from equipment |
---|
2119 | breakrate[0] += sd->break_weapon_rate; |
---|
2120 | breakrate[1] += sd->break_armor_rate; |
---|
2121 | } |
---|
2122 | if (sc) { |
---|
2123 | if (sc->data[SC_MELTDOWN]) { |
---|
2124 | breakrate[0] += sc->data[SC_MELTDOWN]->val2; |
---|
2125 | breakrate[1] += sc->data[SC_MELTDOWN]->val3; |
---|
2126 | } |
---|
2127 | } |
---|
2128 | if (breakrate[0]) |
---|
2129 | skill_break_equip(target, EQP_WEAPON, breakrate[0], BCT_ENEMY); |
---|
2130 | if (breakrate[1]) |
---|
2131 | skill_break_equip(target, EQP_ARMOR, breakrate[1], BCT_ENEMY); |
---|
2132 | } |
---|
2133 | } |
---|
2134 | |
---|
2135 | //SG_FUSION hp penalty [Komurka] |
---|
2136 | if (sc && sc->data[SC_FUSION]) |
---|
2137 | { |
---|
2138 | int hp= sstatus->max_hp; |
---|
2139 | if (sd && tsd) { |
---|
2140 | hp = 8*hp/100; |
---|
2141 | if (100*sstatus->hp <= 20*sstatus->max_hp) |
---|
2142 | hp = sstatus->hp; |
---|
2143 | } else |
---|
2144 | hp = 5*hp/1000; |
---|
2145 | status_zap(src, hp, 0); |
---|
2146 | } |
---|
2147 | |
---|
2148 | return wd; |
---|
2149 | } |
---|
2150 | |
---|
2151 | /*========================================== |
---|
2152 | * battle_calc_magic_attack [DracoRPG] |
---|
2153 | *------------------------------------------*/ |
---|
2154 | struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) |
---|
2155 | { |
---|
2156 | int i, nk; |
---|
2157 | short s_ele; |
---|
2158 | unsigned int skillratio = 100; //Skill dmg modifiers. |
---|
2159 | |
---|
2160 | struct map_session_data *sd, *tsd; |
---|
2161 | struct Damage ad; |
---|
2162 | struct status_data *sstatus = status_get_status_data(src); |
---|
2163 | struct status_data *tstatus = status_get_status_data(target); |
---|
2164 | struct { |
---|
2165 | unsigned imdef : 1; |
---|
2166 | unsigned infdef : 1; |
---|
2167 | } flag; |
---|
2168 | |
---|
2169 | memset(&ad,0,sizeof(ad)); |
---|
2170 | memset(&flag,0,sizeof(flag)); |
---|
2171 | |
---|
2172 | if(src==NULL || target==NULL) |
---|
2173 | { |
---|
2174 | nullpo_info(NLP_MARK); |
---|
2175 | return ad; |
---|
2176 | } |
---|
2177 | //Initial Values |
---|
2178 | ad.damage = 1; |
---|
2179 | ad.div_=skill_get_num(skill_num,skill_lv); |
---|
2180 | ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. |
---|
2181 | ad.dmotion=tstatus->dmotion; |
---|
2182 | ad.blewcount = skill_get_blewcount(skill_num,skill_lv); |
---|
2183 | ad.flag=BF_MAGIC|BF_SKILL; |
---|
2184 | ad.dmg_lv=ATK_DEF; |
---|
2185 | nk = skill_get_nk(skill_num); |
---|
2186 | flag.imdef = nk&NK_IGNORE_DEF?1:0; |
---|
2187 | |
---|
2188 | sd = BL_CAST(BL_PC, src); |
---|
2189 | tsd = BL_CAST(BL_PC, target); |
---|
2190 | |
---|
2191 | //Initialize variables that will be used afterwards |
---|
2192 | s_ele = skill_get_ele(skill_num, skill_lv); |
---|
2193 | |
---|
2194 | if (s_ele == -1) // pl=-1 : the skill takes the weapon's element |
---|
2195 | s_ele = sstatus->rhw.ele; |
---|
2196 | else if (s_ele == -2) //Use status element |
---|
2197 | s_ele = status_get_attack_sc_element(src,status_get_sc(src)); |
---|
2198 | |
---|
2199 | //Set miscellaneous data that needs be filled |
---|
2200 | if(sd) { |
---|
2201 | sd->state.arrow_atk = 0; |
---|
2202 | ad.blewcount += battle_blewcount_bonus(sd, skill_num); |
---|
2203 | } |
---|
2204 | |
---|
2205 | //Skill Range Criteria |
---|
2206 | ad.flag |= battle_range_type(src, target, skill_num, skill_lv); |
---|
2207 | flag.infdef=(tstatus->mode&MD_PLANT?1:0); |
---|
2208 | |
---|
2209 | switch(skill_num) |
---|
2210 | { |
---|
2211 | case MG_FIREWALL: |
---|
2212 | case NJ_KAENSIN: |
---|
2213 | ad.dmotion = 0; //No flinch animation. |
---|
2214 | if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) ) |
---|
2215 | ad.blewcount = 0; //No knockback |
---|
2216 | break; |
---|
2217 | case PR_SANCTUARY: |
---|
2218 | ad.dmotion = 0; //No flinch animation. |
---|
2219 | break; |
---|
2220 | } |
---|
2221 | |
---|
2222 | if (!flag.infdef) //No need to do the math for plants |
---|
2223 | { |
---|
2224 | |
---|
2225 | //MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc |
---|
2226 | #define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; } |
---|
2227 | //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage |
---|
2228 | #define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; } |
---|
2229 | //Adds an absolute value to damage. 100 = +100 damage |
---|
2230 | #define MATK_ADD( a ) { ad.damage+= a; } |
---|
2231 | |
---|
2232 | switch (skill_num) |
---|
2233 | { //Calc base damage according to skill |
---|
2234 | case AL_HEAL: |
---|
2235 | case PR_BENEDICTIO: |
---|
2236 | //Begin Custom Job (blackmagic) |
---|
2237 | case AD_DARKHEAL: // Adept Dark Heal |
---|
2238 | //end custom job |
---|
2239 | ad.damage = skill_calc_heal(src, target, skill_lv)/2; |
---|
2240 | break; |
---|
2241 | case PR_ASPERSIO: |
---|
2242 | ad.damage = 40; |
---|
2243 | break; |
---|
2244 | case PR_SANCTUARY: |
---|
2245 | ad.damage = (skill_lv>6)?388:skill_lv*50; |
---|
2246 | break; |
---|
2247 | case ALL_RESURRECTION: |
---|
2248 | case PR_TURNUNDEAD: |
---|
2249 | //Undead check is on skill_castend_damageid code. |
---|
2250 | i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) |
---|
2251 | + 200 - 200*tstatus->hp/tstatus->max_hp; |
---|
2252 | if(i > 700) i = 700; |
---|
2253 | if(rand()%1000 < i && !(tstatus->mode&MD_BOSS)) |
---|
2254 | ad.damage = tstatus->hp; |
---|
2255 | else |
---|
2256 | ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; |
---|
2257 | break; |
---|
2258 | case PF_SOULBURN: |
---|
2259 | ad.damage = tstatus->sp * 2; |
---|
2260 | break; |
---|
2261 | default: |
---|
2262 | { |
---|
2263 | if (sstatus->matk_max > sstatus->matk_min) { |
---|
2264 | MATK_ADD(sstatus->matk_min+rand()%(1+sstatus->matk_max-sstatus->matk_min)); |
---|
2265 | } else { |
---|
2266 | MATK_ADD(sstatus->matk_min); |
---|
2267 | } |
---|
2268 | |
---|
2269 | if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill |
---|
2270 | if(mflag>0) |
---|
2271 | ad.damage/= mflag; |
---|
2272 | else |
---|
2273 | ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); |
---|
2274 | } |
---|
2275 | |
---|
2276 | switch(skill_num){ |
---|
2277 | case MG_NAPALMBEAT: |
---|
2278 | case MG_FIREBALL: |
---|
2279 | skillratio += skill_lv*10-30; |
---|
2280 | break; |
---|
2281 | case MG_SOULSTRIKE: |
---|
2282 | if (battle_check_undead(tstatus->race,tstatus->def_ele)) |
---|
2283 | skillratio += 5*skill_lv; |
---|
2284 | break; |
---|
2285 | case MG_FIREWALL: |
---|
2286 | skillratio -= 50; |
---|
2287 | break; |
---|
2288 | case MG_THUNDERSTORM: |
---|
2289 | skillratio -= 20; |
---|
2290 | break; |
---|
2291 | case MG_FROSTDIVER: |
---|
2292 | skillratio += 10*skill_lv; |
---|
2293 | break; |
---|
2294 | case AL_HOLYLIGHT: |
---|
2295 | skillratio += 25; |
---|
2296 | if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST) |
---|
2297 | skillratio *= 5; //Does 5x damage include bonuses from other skills? |
---|
2298 | break; |
---|
2299 | case AL_RUWACH: |
---|
2300 | skillratio += 45; |
---|
2301 | break; |
---|
2302 | case WZ_FROSTNOVA: |
---|
2303 | skillratio += (100+skill_lv*10)*2/3-100; |
---|
2304 | break; |
---|
2305 | case WZ_FIREPILLAR: |
---|
2306 | if (skill_lv > 10) |
---|
2307 | skillratio += 100; |
---|
2308 | else |
---|
2309 | skillratio -= 80; |
---|
2310 | break; |
---|
2311 | case WZ_SIGHTRASHER: |
---|
2312 | skillratio += 20*skill_lv; |
---|
2313 | break; |
---|
2314 | case WZ_VERMILION: |
---|
2315 | skillratio += 20*skill_lv-20; |
---|
2316 | break; |
---|
2317 | case WZ_WATERBALL: |
---|
2318 | skillratio += 30*skill_lv; |
---|
2319 | break; |
---|
2320 | case WZ_STORMGUST: |
---|
2321 | skillratio += 40*skill_lv; |
---|
2322 | break; |
---|
2323 | case HW_NAPALMVULCAN: |
---|
2324 | skillratio += 10*skill_lv-30; |
---|
2325 | break; |
---|
2326 | case SL_STIN: |
---|
2327 | skillratio += (tstatus->size?-99:10*skill_lv); //target size must be small (0) for full damage. |
---|
2328 | break; |
---|
2329 | case SL_STUN: |
---|
2330 | skillratio += (tstatus->size!=2?5*skill_lv:-99); //Full damage is dealt on small/medium targets |
---|
2331 | break; |
---|
2332 | case SL_SMA: |
---|
2333 | skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv% |
---|
2334 | break; |
---|
2335 | case NJ_KOUENKA: |
---|
2336 | skillratio -= 10; |
---|
2337 | break; |
---|
2338 | case NJ_KAENSIN: |
---|
2339 | skillratio -= 50; |
---|
2340 | break; |
---|
2341 | case NJ_BAKUENRYU: |
---|
2342 | skillratio += 50*(skill_lv-1); |
---|
2343 | break; |
---|
2344 | case NJ_HYOUSYOURAKU: |
---|
2345 | skillratio += 50*skill_lv; |
---|
2346 | break; |
---|
2347 | case NJ_RAIGEKISAI: |
---|
2348 | skillratio += 60 + 40*skill_lv; |
---|
2349 | break; |
---|
2350 | case NJ_KAMAITACHI: |
---|
2351 | case NPC_ENERGYDRAIN: |
---|
2352 | skillratio += 100*skill_lv; |
---|
2353 | break; |
---|
2354 | case NPC_EARTHQUAKE: |
---|
2355 | skillratio += 100 +100*skill_lv +100*(skill_lv/2); |
---|
2356 | break; |
---|
2357 | //Begin Custom Job (blackmagic) |
---|
2358 | case NC_DRAINLIFE: // Necro Drain Life [Brain] |
---|
2359 | skillratio += 25*skill_lv; |
---|
2360 | break; |
---|
2361 | case WL_HELLFIRE: // Warlock Hellfire [Brain] |
---|
2362 | skillratio += 25*skill_lv; |
---|
2363 | break; |
---|
2364 | case WL_SHADOWBURN: // Warlock Shadow Burn [Brain] |
---|
2365 | skillratio += 20*skill_lv; |
---|
2366 | break; |
---|
2367 | case WL_CURSEDOOM: // Warlock Curse of Doom [Brain] |
---|
2368 | skillratio += 400 + 300*skill_lv; //max 20*matk dmg after 60 seconds |
---|
2369 | break; |
---|
2370 | case WL_SEARING: // Warlock Searing Pain [Brain] |
---|
2371 | if(status_get_sc(target)->data[SC_SEARING]) |
---|
2372 | skillratio = 10*pc_checkskill(sd,WL_SEARING);//10% * skilllv |
---|
2373 | break; //Else 100% Matk |
---|
2374 | case WL_IMMOLATE: // Warlock Immolate [Brain] |
---|
2375 | if(status_get_sc(target)->data[SC_IMMOLATE]) |
---|
2376 | skillratio += 10*pc_checkskill(sd,WL_SEARING);//100% +10 * searing lv |
---|
2377 | else skillratio += -20 + 20*skill_lv;// Else 80% + 20% * skill lv |
---|
2378 | break; |
---|
2379 | case WL_CONFLAGRATE: // Warlock Conflagrate [Brain] |
---|
2380 | skillratio += 100 + 60*skill_lv + //damage bonus from other fire skills |
---|
2381 | 10*pc_checkskill(sd,WL_SEARING) + 10*pc_checkskill(sd,WL_IMMOLATE); |
---|
2382 | break; |
---|
2383 | //End Custom Job |
---|
2384 | } |
---|
2385 | |
---|
2386 | MATK_RATE(skillratio); |
---|
2387 | |
---|
2388 | //Constant/misc additions from skills |
---|
2389 | if (skill_num == WZ_FIREPILLAR) |
---|
2390 | MATK_ADD(50); |
---|
2391 | } |
---|
2392 | } |
---|
2393 | |
---|
2394 | if(sd) { |
---|
2395 | //Damage bonuses |
---|
2396 | if ((i = pc_skillatk_bonus(sd, skill_num))) |
---|
2397 | ad.damage += ad.damage*i/100; |
---|
2398 | |
---|
2399 | //Ignore Defense? |
---|
2400 | if (!flag.imdef && ( |
---|
2401 | sd->ignore_mdef_ele & (1<<tstatus->def_ele) || |
---|
2402 | sd->ignore_mdef_race & (1<<tstatus->race) || |
---|
2403 | sd->ignore_mdef_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) |
---|
2404 | )) |
---|
2405 | flag.imdef = 1; |
---|
2406 | } |
---|
2407 | |
---|
2408 | if(!flag.imdef){ |
---|
2409 | char mdef = tstatus->mdef; |
---|
2410 | int mdef2= tstatus->mdef2; |
---|
2411 | if(sd) { |
---|
2412 | i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS]; |
---|
2413 | i+= sd->ignore_mdef[tstatus->race]; |
---|
2414 | if (i) |
---|
2415 | { |
---|
2416 | if (i > 100) i = 100; |
---|
2417 | mdef -= mdef * i/100; |
---|
2418 | //mdef2-= mdef2* i/100; |
---|
2419 | } |
---|
2420 | } |
---|
2421 | if(battle_config.magic_defense_type) |
---|
2422 | ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2; |
---|
2423 | else |
---|
2424 | ad.damage = ad.damage * (100-mdef)/100 - mdef2; |
---|
2425 | } |
---|
2426 | |
---|
2427 | if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) |
---|
2428 | { //Apply the physical part of the skill's damage. [Skotlex] |
---|
2429 | struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); |
---|
2430 | ad.damage = (wd.damage + ad.damage) * (100 + 40*skill_lv)/100; |
---|
2431 | if(src==target) |
---|
2432 | { |
---|
2433 | if (src->type == BL_PC) |
---|
2434 | ad.damage = ad.damage/2; |
---|
2435 | else |
---|
2436 | ad.damage = 0; |
---|
2437 | } |
---|
2438 | } |
---|
2439 | |
---|
2440 | if (skill_num == NPC_EARTHQUAKE) |
---|
2441 | { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] |
---|
2442 | //Also divide the extra bonuses from atk2 based on the number in range [Kevin] |
---|
2443 | if(mflag>0) |
---|
2444 | ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; |
---|
2445 | else |
---|
2446 | ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); |
---|
2447 | } |
---|
2448 | |
---|
2449 | if(ad.damage<1) |
---|
2450 | ad.damage=1; |
---|
2451 | |
---|
2452 | if (!(nk&NK_NO_ELEFIX)) |
---|
2453 | ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); |
---|
2454 | //Begin Custom Job (blackmagic) |
---|
2455 | if(skill_num == WL_SHADOWBURN) { // Warlock Shadow Burn [Brain] |
---|
2456 | // This is where we calculate the secondary damage |
---|
2457 | if(ad.damage<1) ad.damage=1; |
---|
2458 | struct Damage md = battle_calc_misc_attack(src,target,skill_num,skill_lv, mflag); |
---|
2459 | if(md.damage<1) md.damage=1; |
---|
2460 | ad.damage += md.damage; |
---|
2461 | } |
---|
2462 | //End Custom Job |
---|
2463 | if (sd && !(nk&NK_NO_CARDFIX_ATK)) { |
---|
2464 | short t_class = status_get_class(target); |
---|
2465 | short cardfix=1000; |
---|
2466 | |
---|
2467 | cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; |
---|
2468 | if (!(nk&NK_NO_ELEFIX)) |
---|
2469 | cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; |
---|
2470 | cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; |
---|
2471 | cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; |
---|
2472 | for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) { |
---|
2473 | if(sd->add_mdmg[i].class_ == t_class) { |
---|
2474 | cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100; |
---|
2475 | continue; |
---|
2476 | } |
---|
2477 | } |
---|
2478 | if (cardfix != 1000) |
---|
2479 | MATK_RATE(cardfix/10); |
---|
2480 | } |
---|
2481 | |
---|
2482 | if (tsd && !(nk&NK_NO_CARDFIX_DEF)) |
---|
2483 | { //Target cards. |
---|
2484 | short s_race2=status_get_race2(src); |
---|
2485 | short s_class= status_get_class(src); |
---|
2486 | int cardfix=1000; |
---|
2487 | |
---|
2488 | if (!(nk&NK_NO_ELEFIX)) |
---|
2489 | cardfix=cardfix*(100-tsd->subele[s_ele])/100; |
---|
2490 | cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; |
---|
2491 | cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; |
---|
2492 | cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; |
---|
2493 | cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; |
---|
2494 | for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { |
---|
2495 | if(tsd->add_mdef[i].class_ == s_class) { |
---|
2496 | cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; |
---|
2497 | break; |
---|
2498 | } |
---|
2499 | } |
---|
2500 | //It was discovered that ranged defense also counts vs magic! [Skotlex] |
---|
2501 | if (ad.flag&BF_SHORT) |
---|
2502 | cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; |
---|
2503 | else |
---|
2504 | cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; |
---|
2505 | |
---|
2506 | cardfix=cardfix*(100-tsd->magic_def_rate)/100; |
---|
2507 | |
---|
2508 | if( tsd->sc.data[SC_MDEF_RATE] ) |
---|
2509 | cardfix=cardfix*(100-tsd->sc.data[SC_MDEF_RATE]->val1)/100; |
---|
2510 | |
---|
2511 | if (cardfix != 1000) |
---|
2512 | MATK_RATE(cardfix/10); |
---|
2513 | } |
---|
2514 | } |
---|
2515 | |
---|
2516 | damage_div_fix(ad.damage, ad.div_); |
---|
2517 | |
---|
2518 | if (flag.infdef && ad.damage) |
---|
2519 | ad.damage = ad.damage>0?1:-1; |
---|
2520 | |
---|
2521 | ad.damage=battle_calc_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); |
---|
2522 | if (map_flag_gvg2(target->m)) |
---|
2523 | ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); |
---|
2524 | return ad; |
---|
2525 | } |
---|
2526 | |
---|
2527 | /*========================================== |
---|
2528 | * »ÌŒ_E?[WvZ |
---|
2529 | *------------------------------------------*/ |
---|
2530 | struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) |
---|
2531 | { |
---|
2532 | int skill; |
---|
2533 | short i, nk; |
---|
2534 | short s_ele; |
---|
2535 | |
---|
2536 | struct map_session_data *sd, *tsd; |
---|
2537 | struct Damage md; //DO NOT CONFUSE with md of mob_data! |
---|
2538 | struct status_data *sstatus = status_get_status_data(src); |
---|
2539 | struct status_data *tstatus = status_get_status_data(target); |
---|
2540 | |
---|
2541 | memset(&md,0,sizeof(md)); |
---|
2542 | |
---|
2543 | if( src == NULL || target == NULL ){ |
---|
2544 | nullpo_info(NLP_MARK); |
---|
2545 | return md; |
---|
2546 | } |
---|
2547 | |
---|
2548 | //Some initial values |
---|
2549 | md.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; |
---|
2550 | md.dmotion=tstatus->dmotion; |
---|
2551 | md.div_=skill_get_num( skill_num,skill_lv ); |
---|
2552 | md.blewcount=skill_get_blewcount(skill_num,skill_lv); |
---|
2553 | md.dmg_lv=ATK_DEF; |
---|
2554 | md.flag=BF_MISC|BF_SKILL; |
---|
2555 | |
---|
2556 | nk = skill_get_nk(skill_num); |
---|
2557 | |
---|
2558 | sd = BL_CAST(BL_PC, src); |
---|
2559 | tsd = BL_CAST(BL_PC, target); |
---|
2560 | |
---|
2561 | if(sd) { |
---|
2562 | sd->state.arrow_atk = 0; |
---|
2563 | md.blewcount += battle_blewcount_bonus(sd, skill_num); |
---|
2564 | } |
---|
2565 | |
---|
2566 | s_ele = skill_get_ele(skill_num, skill_lv); |
---|
2567 | if (s_ele < 0) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] |
---|
2568 | s_ele = ELE_NEUTRAL; |
---|
2569 | |
---|
2570 | //Skill Range Criteria |
---|
2571 | md.flag |= battle_range_type(src, target, skill_num, skill_lv); |
---|
2572 | |
---|
2573 | switch(skill_num){ |
---|
2574 | case HT_LANDMINE: |
---|
2575 | md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100; |
---|
2576 | break; |
---|
2577 | case HT_BLASTMINE: |
---|
2578 | md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100; |
---|
2579 | break; |
---|
2580 | case HT_CLAYMORETRAP: |
---|
2581 | md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100; |
---|
2582 | break; |
---|
2583 | case HT_BLITZBEAT: |
---|
2584 | case SN_FALCONASSAULT: |
---|
2585 | //Blitz-beat Damage. |
---|
2586 | if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) |
---|
2587 | skill=0; |
---|
2588 | md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2; |
---|
2589 | if(mflag > 1) //Autocasted Blitz. |
---|
2590 | nk|=NK_SPLASHSPLIT; |
---|
2591 | |
---|
2592 | if (skill_num == SN_FALCONASSAULT) |
---|
2593 | { |
---|
2594 | //Div fix of Blitzbeat |
---|
2595 | skill = skill_get_num(HT_BLITZBEAT, 5); |
---|
2596 | damage_div_fix(md.damage, skill); |
---|
2597 | |
---|
2598 | //Falcon Assault Modifier |
---|
2599 | md.damage=md.damage*(150+70*skill_lv)/100; |
---|
2600 | } |
---|
2601 | break; |
---|
2602 | case TF_THROWSTONE: |
---|
2603 | md.damage=50; |
---|
2604 | break; |
---|
2605 | case BA_DISSONANCE: |
---|
2606 | md.damage=30+skill_lv*10; |
---|
2607 | if (sd) |
---|
2608 | md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON); |
---|
2609 | break; |
---|
2610 | case NPC_SELFDESTRUCTION: |
---|
2611 | md.damage = sstatus->hp; |
---|
2612 | break; |
---|
2613 | case NPC_SMOKING: |
---|
2614 | md.damage=3; |
---|
2615 | break; |
---|
2616 | case NPC_DARKBREATH: |
---|
2617 | md.damage = 500 + (skill_lv-1)*1000 + rand()%1000; |
---|
2618 | if(md.damage > 9999) md.damage = 9999; |
---|
2619 | break; |
---|
2620 | case PA_PRESSURE: |
---|
2621 | md.damage=500+300*skill_lv; |
---|
2622 | break; |
---|
2623 | case PA_GOSPEL: |
---|
2624 | md.damage = 1+rand()%9999; |
---|
2625 | break; |
---|
2626 | case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen] |
---|
2627 | if(tstatus->vit+sstatus->int_) //crash fix |
---|
2628 | md.damage = 7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_)); |
---|
2629 | else |
---|
2630 | md.damage = 0; |
---|
2631 | if (tsd) md.damage>>=1; |
---|
2632 | if (md.damage < 0 || md.damage > INT_MAX>>1) |
---|
2633 | //Overflow prevention, will anyone whine if I cap it to a few billion? |
---|
2634 | //Not capped to INT_MAX to give some room for further damage increase. |
---|
2635 | md.damage = INT_MAX>>1; |
---|
2636 | break; |
---|
2637 | case NJ_ZENYNAGE: |
---|
2638 | md.damage = skill_get_zeny(skill_num ,skill_lv); |
---|
2639 | if (!md.damage) md.damage = 2; |
---|
2640 | md.damage = md.damage + rand()%md.damage; |
---|
2641 | if (is_boss(target)) |
---|
2642 | md.damage=md.damage/3; |
---|
2643 | else if (tsd) |
---|
2644 | md.damage=md.damage/2; |
---|
2645 | break; |
---|
2646 | case GS_FLING: |
---|
2647 | md.damage = sd?sd->status.job_level:status_get_lv(src); |
---|
2648 | break; |
---|
2649 | case HVAN_EXPLOSION: //[orn] |
---|
2650 | md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ; |
---|
2651 | break ; |
---|
2652 | case ASC_BREAKER: |
---|
2653 | md.damage = 500+rand()%500 + 5*skill_lv * sstatus->int_; |
---|
2654 | nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part. |
---|
2655 | break; |
---|
2656 | case HW_GRAVITATION: |
---|
2657 | md.damage = 200+200*skill_lv; |
---|
2658 | md.dmotion = 0; //No flinch animation. |
---|
2659 | break; |
---|
2660 | case NPC_EVILLAND: |
---|
2661 | md.damage = (skill_lv>6)?666:skill_lv*100; |
---|
2662 | //Begin Custom Job (blackmagic) |
---|
2663 | case WL_SHADOWBURN: // Warlock ShadowBurn dark element damage [Brain] |
---|
2664 | s_ele = ELE_DARK; |
---|
2665 | md.damage = ((300 + 20*skill_lv)/100)*((sstatus->int_*(rand()%300+500))/100); //Fixed between min and max matk for now |
---|
2666 | //End Custom Job |
---|
2667 | break; |
---|
2668 | } |
---|
2669 | |
---|
2670 | if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets |
---|
2671 | if(mflag>0) |
---|
2672 | md.damage/= mflag; |
---|
2673 | else |
---|
2674 | ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); |
---|
2675 | } |
---|
2676 | |
---|
2677 | damage_div_fix(md.damage, md.div_); |
---|
2678 | |
---|
2679 | if (!(nk&NK_IGNORE_FLEE)) |
---|
2680 | { |
---|
2681 | struct status_change *sc = status_get_sc(target); |
---|
2682 | i = 0; //Temp for "hit or no hit" |
---|
2683 | if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT) |
---|
2684 | i = 1; |
---|
2685 | else { |
---|
2686 | short |
---|
2687 | flee = tstatus->flee, |
---|
2688 | hitrate=80; //Default hitrate |
---|
2689 | |
---|
2690 | if(battle_config.agi_penalty_type && |
---|
2691 | battle_config.agi_penalty_target&target->type) |
---|
2692 | { |
---|
2693 | unsigned char attacker_count; //256 max targets should be a sane max |
---|
2694 | attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv); |
---|
2695 | if(attacker_count >= battle_config.agi_penalty_count) |
---|
2696 | { |
---|
2697 | if (battle_config.agi_penalty_type == 1) |
---|
2698 | flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; |
---|
2699 | else //asume type 2: absolute reduction |
---|
2700 | flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; |
---|
2701 | if(flee < 1) flee = 1; |
---|
2702 | } |
---|
2703 | } |
---|
2704 | |
---|
2705 | hitrate+= sstatus->hit - flee; |
---|
2706 | hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); |
---|
2707 | |
---|
2708 | if(rand()%100 < hitrate) |
---|
2709 | i = 1; |
---|
2710 | } |
---|
2711 | if (!i) { |
---|
2712 | md.damage = 0; |
---|
2713 | md.dmg_lv=ATK_FLEE; |
---|
2714 | } |
---|
2715 | } |
---|
2716 | |
---|
2717 | if(md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF)){ |
---|
2718 | int cardfix = 10000; |
---|
2719 | int race2 = status_get_race2(src); |
---|
2720 | if (!(nk&NK_NO_ELEFIX)) |
---|
2721 | cardfix=cardfix*(100-tsd->subele[s_ele])/100; |
---|
2722 | cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; |
---|
2723 | cardfix=cardfix*(100-tsd->subrace2[race2])/100; |
---|
2724 | cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; |
---|
2725 | cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; |
---|
2726 | cardfix=cardfix*(100-tsd->misc_def_rate)/100; |
---|
2727 | if(md.flag&BF_SHORT) |
---|
2728 | cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; |
---|
2729 | else // BF_LONG (there's no other choice) |
---|
2730 | cardfix=cardfix*(100-tsd->long_attack_def_rate)/100; |
---|
2731 | |
---|
2732 | if (cardfix != 10000) |
---|
2733 | md.damage=md.damage*cardfix/10000; |
---|
2734 | } |
---|
2735 | |
---|
2736 | if (sd && (i = pc_skillatk_bonus(sd, skill_num))) |
---|
2737 | md.damage += md.damage*i/100; |
---|
2738 | |
---|
2739 | if(md.damage < 0) |
---|
2740 | md.damage = 0; |
---|
2741 | else if(md.damage && tstatus->mode&MD_PLANT) |
---|
2742 | md.damage = 1; |
---|
2743 | |
---|
2744 | if(!(nk&NK_NO_ELEFIX)) |
---|
2745 | md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); |
---|
2746 | |
---|
2747 | md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); |
---|
2748 | if (map_flag_gvg2(target->m)) |
---|
2749 | md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); |
---|
2750 | |
---|
2751 | if (skill_num == NJ_ZENYNAGE && sd) |
---|
2752 | { //Time to Pay Up. |
---|
2753 | if ( md.damage > sd->status.zeny ) |
---|
2754 | md.damage=sd->status.zeny; |
---|
2755 | pc_payzeny(sd, md.damage); |
---|
2756 | } |
---|
2757 | |
---|
2758 | return md; |
---|
2759 | } |
---|
2760 | /*========================================== |
---|
2761 | * _E?[WvZê?E?p |
---|
2762 | *------------------------------------------*/ |
---|
2763 | struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count) |
---|
2764 | { |
---|
2765 | struct Damage d; |
---|
2766 | switch(attack_type) { |
---|
2767 | case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); break; |
---|
2768 | case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count); break; |
---|
2769 | case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count); break; |
---|
2770 | default: |
---|
2771 | ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type); |
---|
2772 | memset(&d,0,sizeof(d)); |
---|
2773 | break; |
---|
2774 | } |
---|
2775 | if (d.damage + d.damage2 < 1) |
---|
2776 | { //Miss/Absorbed |
---|
2777 | //Weapon attacks should go through to cause additional effects. |
---|
2778 | if (d.dmg_lv != ATK_LUCKY && attack_type&(BF_MAGIC|BF_MISC)) |
---|
2779 | d.dmg_lv = ATK_FLEE; |
---|
2780 | d.dmotion = 0; |
---|
2781 | } |
---|
2782 | return d; |
---|
2783 | } |
---|
2784 | |
---|
2785 | //Calculates BF_WEAPON returned damage. |
---|
2786 | int battle_calc_return_damage(struct block_list* bl, int damage, int flag) |
---|
2787 | { |
---|
2788 | struct map_session_data* sd = NULL; |
---|
2789 | int rdamage = 0; |
---|
2790 | |
---|
2791 | sd = BL_CAST(BL_PC, bl); |
---|
2792 | |
---|
2793 | //Bounces back part of the damage. |
---|
2794 | if (flag & BF_SHORT) { |
---|
2795 | struct status_change* sc; |
---|
2796 | if (sd && sd->short_weapon_damage_return) |
---|
2797 | { |
---|
2798 | rdamage += damage * sd->short_weapon_damage_return / 100; |
---|
2799 | if(rdamage < 1) rdamage = 1; |
---|
2800 | } |
---|
2801 | sc = status_get_sc(bl); |
---|
2802 | if (sc && sc->data[SC_REFLECTSHIELD]) |
---|
2803 | { |
---|
2804 | rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; |
---|
2805 | if (rdamage < 1) rdamage = 1; |
---|
2806 | } |
---|
2807 | } else { |
---|
2808 | if (sd && sd->long_weapon_damage_return) |
---|
2809 | { |
---|
2810 | rdamage += damage * sd->long_weapon_damage_return / 100; |
---|
2811 | if (rdamage < 1) rdamage = 1; |
---|
2812 | } |
---|
2813 | } |
---|
2814 | return rdamage; |
---|
2815 | } |
---|
2816 | |
---|
2817 | void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss) |
---|
2818 | { |
---|
2819 | struct weapon_data *wd; |
---|
2820 | int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage; |
---|
2821 | for (i = 0; i < 4; i++) { |
---|
2822 | //First two iterations: Right hand |
---|
2823 | if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; } |
---|
2824 | else { wd = &sd->left_weapon; damage = &ldamage; } |
---|
2825 | if (*damage <= 0) continue; |
---|
2826 | //First and Third iterations: race, other two boss/nonboss state |
---|
2827 | if (i == 0 || i == 2) |
---|
2828 | type = race; |
---|
2829 | else |
---|
2830 | type = boss?RC_BOSS:RC_NONBOSS; |
---|
2831 | |
---|
2832 | hp = wd->hp_drain[type].value; |
---|
2833 | if (wd->hp_drain[type].rate) |
---|
2834 | hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per); |
---|
2835 | |
---|
2836 | sp = wd->sp_drain[type].value; |
---|
2837 | if (wd->sp_drain[type].rate) |
---|
2838 | sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per); |
---|
2839 | |
---|
2840 | if (hp) { |
---|
2841 | if (wd->hp_drain[type].type) |
---|
2842 | rhp += hp; |
---|
2843 | thp += hp; |
---|
2844 | } |
---|
2845 | if (sp) { |
---|
2846 | if (wd->sp_drain[type].type) |
---|
2847 | rsp += sp; |
---|
2848 | tsp += sp; |
---|
2849 | } |
---|
2850 | } |
---|
2851 | |
---|
2852 | if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate) |
---|
2853 | status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false); |
---|
2854 | //begin custom job (blackmagic |
---|
2855 | // Adept Blood Pact drains 5% damage per hit [FlavioJS/Brain] |
---|
2856 | if( pc_checkskill(sd, AD_BLOODPACT) > 0 ) |
---|
2857 | thp += battle_calc_drain(rdamage,1000,5); |
---|
2858 | |
---|
2859 | // Warlock Soul Steal drains 1%*skilllv damage per hit [Brain] |
---|
2860 | if( pc_checkskill(sd, WL_SOULSTEAL) > 0 ) |
---|
2861 | tsp += battle_calc_drain(rdamage,1000,pc_checkskill(sd,WL_SOULSTEAL)); |
---|
2862 | // Warlock Touch of Corruption burns 1%*skilllv damage as SP per hit [Brain] |
---|
2863 | if( pc_checkskill(sd, WL_CORRUPTION) > 0 ) { |
---|
2864 | int corrupt_sp; |
---|
2865 | corrupt_sp = battle_calc_drain(rdamage,1000,pc_checkskill(sd,WL_CORRUPTION)); |
---|
2866 | if(status_damage(NULL, tbl, 0, corrupt_sp, 0, 3)) |
---|
2867 | rhp += corrupt_sp;//If SP damage was caused, increase HP damage too |
---|
2868 | } |
---|
2869 | //end custom job |
---|
2870 | if (!thp && !tsp) return; |
---|
2871 | |
---|
2872 | status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1); |
---|
2873 | |
---|
2874 | if (rhp || rsp) |
---|
2875 | status_zap(tbl, rhp, rsp); |
---|
2876 | } |
---|
2877 | |
---|
2878 | /*========================================== |
---|
2879 | * Ê?EU?E?ÜÆß |
---|
2880 | *------------------------------------------*/ |
---|
2881 | enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) |
---|
2882 | { |
---|
2883 | struct map_session_data *sd = NULL, *tsd = NULL; |
---|
2884 | struct status_data *sstatus, *tstatus; |
---|
2885 | struct status_change *sc, *tsc; |
---|
2886 | int damage,rdamage=0,rdelay=0; |
---|
2887 | int skillv; |
---|
2888 | struct Damage wd; |
---|
2889 | |
---|
2890 | nullpo_retr(ATK_NONE, src); |
---|
2891 | nullpo_retr(ATK_NONE, target); |
---|
2892 | |
---|
2893 | if (src->prev == NULL || target->prev == NULL) |
---|
2894 | return ATK_NONE; |
---|
2895 | |
---|
2896 | sd = BL_CAST(BL_PC, src); |
---|
2897 | tsd = BL_CAST(BL_PC, target); |
---|
2898 | |
---|
2899 | sstatus = status_get_status_data(src); |
---|
2900 | tstatus = status_get_status_data(target); |
---|
2901 | |
---|
2902 | sc = status_get_sc(src); |
---|
2903 | tsc = status_get_sc(target); |
---|
2904 | |
---|
2905 | if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex] |
---|
2906 | sc = NULL; |
---|
2907 | if (tsc && !tsc->count) |
---|
2908 | tsc = NULL; |
---|
2909 | |
---|
2910 | if (sd) |
---|
2911 | { |
---|
2912 | sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)); |
---|
2913 | if (sd->state.arrow_atk) |
---|
2914 | { |
---|
2915 | int index = sd->equip_index[EQI_AMMO]; |
---|
2916 | if (index<0) { |
---|
2917 | clif_arrow_fail(sd,0); |
---|
2918 | return ATK_NONE; |
---|
2919 | } |
---|
2920 | //Ammo check by Ishizu-chan |
---|
2921 | if (sd->inventory_data[index]) |
---|
2922 | switch (sd->status.weapon) { |
---|
2923 | case W_BOW: |
---|
2924 | if (sd->inventory_data[index]->look != A_ARROW) { |
---|
2925 | clif_arrow_fail(sd,0); |
---|
2926 | return ATK_NONE; |
---|
2927 | } |
---|
2928 | break; |
---|
2929 | case W_REVOLVER: |
---|
2930 | case W_RIFLE: |
---|
2931 | case W_GATLING: |
---|
2932 | case W_SHOTGUN: |
---|
2933 | if (sd->inventory_data[index]->look != A_BULLET) { |
---|
2934 | clif_arrow_fail(sd,0); |
---|
2935 | return ATK_NONE; |
---|
2936 | } |
---|
2937 | break; |
---|
2938 | case W_GRENADE: |
---|
2939 | if (sd->inventory_data[index]->look != A_GRENADE) { |
---|
2940 | clif_arrow_fail(sd,0); |
---|
2941 | return ATK_NONE; |
---|
2942 | } |
---|
2943 | break; |
---|
2944 | } |
---|
2945 | } |
---|
2946 | } |
---|
2947 | |
---|
2948 | if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2)) |
---|
2949 | status_change_end(src,SC_CLOAKING,-1); |
---|
2950 | |
---|
2951 | //Check for counter attacks that block your attack. [Skotlex] |
---|
2952 | if(tsc) |
---|
2953 | { |
---|
2954 | if(tsc->data[SC_AUTOCOUNTER] && |
---|
2955 | status_check_skilluse(target, src, KN_AUTOCOUNTER, 1) |
---|
2956 | ) { |
---|
2957 | int dir = map_calc_dir(target,src->x,src->y); |
---|
2958 | int t_dir = unit_getdir(target); |
---|
2959 | int dist = distance_bl(src, target); |
---|
2960 | if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) |
---|
2961 | { |
---|
2962 | int skilllv = tsc->data[SC_AUTOCOUNTER]->val1; |
---|
2963 | clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] |
---|
2964 | clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. |
---|
2965 | status_change_end(target,SC_AUTOCOUNTER,-1); |
---|
2966 | skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0); |
---|
2967 | return ATK_NONE; |
---|
2968 | } |
---|
2969 | } |
---|
2970 | if (tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src)) { |
---|
2971 | int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1; |
---|
2972 | int duration = skill_get_time2(MO_BLADESTOP,skilllv); |
---|
2973 | status_change_end(target, SC_BLADESTOP_WAIT, -1); |
---|
2974 | if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, (int)target, duration)) |
---|
2975 | { //Target locked. |
---|
2976 | clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. |
---|
2977 | clif_bladestop(target,src,1); |
---|
2978 | sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0,(int)src, duration); |
---|
2979 | return ATK_NONE; |
---|
2980 | } |
---|
2981 | } |
---|
2982 | } |
---|
2983 | |
---|
2984 | if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) |
---|
2985 | { |
---|
2986 | int triple_rate= 30 - skillv; //Base Rate |
---|
2987 | if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) |
---|
2988 | { |
---|
2989 | triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100; |
---|
2990 | status_change_end(src,SC_SKILLRATE_UP,-1); |
---|
2991 | } |
---|
2992 | if (rand()%100 < triple_rate) |
---|
2993 | //FIXME: invalid return type! |
---|
2994 | return (damage_lv)skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0); |
---|
2995 | } |
---|
2996 | |
---|
2997 | if (sc) |
---|
2998 | { |
---|
2999 | if (sc->data[SC_SACRIFICE]) |
---|
3000 | //FIXME: invalid return type! |
---|
3001 | return (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE]->val1,tick,0); |
---|
3002 | if (sc->data[SC_MAGICALATTACK]) |
---|
3003 | //FIXME: invalid return type! |
---|
3004 | return (damage_lv)skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0); |
---|
3005 | } |
---|
3006 | |
---|
3007 | wd = battle_calc_weapon_attack(src, target, 0, 0, flag); |
---|
3008 | |
---|
3009 | if (sd && sd->state.arrow_atk) //Consume arrow. |
---|
3010 | battle_consume_ammo(sd, 0, 0); |
---|
3011 | |
---|
3012 | damage = wd.damage + wd.damage2; |
---|
3013 | if (damage > 0 && src != target) { |
---|
3014 | rdamage = battle_calc_return_damage(target, damage, wd.flag); |
---|
3015 | if (rdamage > 0) { |
---|
3016 | rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); |
---|
3017 | //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] |
---|
3018 | skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,tick); |
---|
3019 | } |
---|
3020 | } |
---|
3021 | |
---|
3022 | wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); |
---|
3023 | |
---|
3024 | if (sd && sd->splash_range > 0 && damage > 0) |
---|
3025 | skill_castend_damage_id(src, target, 0, 1, tick, 0); |
---|
3026 | |
---|
3027 | map_freeblock_lock(); |
---|
3028 | |
---|
3029 | battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion); |
---|
3030 | |
---|
3031 | if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) { |
---|
3032 | int sp = 0; |
---|
3033 | int skillid = sc->data[SC_AUTOSPELL]->val2; |
---|
3034 | int skilllv = sc->data[SC_AUTOSPELL]->val3; |
---|
3035 | int i = rand()%100; |
---|
3036 | if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) |
---|
3037 | i = 0; //Max chance, no skilllv reduction. [Skotlex] |
---|
3038 | if (i >= 50) skilllv -= 2; |
---|
3039 | else if (i >= 15) skilllv--; |
---|
3040 | if (skilllv < 1) skilllv = 1; |
---|
3041 | sp = skill_get_sp(skillid,skilllv) * 2 / 3; |
---|
3042 | |
---|
3043 | if (status_charge(src, 0, sp)) { |
---|
3044 | switch (skill_get_casttype(skillid)) { |
---|
3045 | case CAST_GROUND: |
---|
3046 | skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag); |
---|
3047 | break; |
---|
3048 | case CAST_NODAMAGE: |
---|
3049 | skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag); |
---|
3050 | break; |
---|
3051 | case CAST_DAMAGE: |
---|
3052 | skill_castend_damage_id(src, target, skillid, skilllv, tick, flag); |
---|
3053 | break; |
---|
3054 | } |
---|
3055 | } |
---|
3056 | } |
---|
3057 | if (sd) { |
---|
3058 | if (wd.flag & BF_WEAPON && src != target && damage > 0) { |
---|
3059 | if (battle_config.left_cardfix_to_right) |
---|
3060 | battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target)); |
---|
3061 | else |
---|
3062 | battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); |
---|
3063 | } |
---|
3064 | } |
---|
3065 | if (rdamage > 0) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex] |
---|
3066 | if(tsd && src != target) |
---|
3067 | battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); |
---|
3068 | battle_delay_damage(tick, wd.amotion, target, src, 0, 0, 0, rdamage, ATK_DEF, rdelay); |
---|
3069 | } |
---|
3070 | |
---|
3071 | if (tsc) { |
---|
3072 | if (tsc->data[SC_POISONREACT] && |
---|
3073 | (rand()%100 < tsc->data[SC_POISONREACT]->val3 |
---|
3074 | || sstatus->def_ele == ELE_POISON) && |
---|
3075 | // check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O; |
---|
3076 | status_check_skilluse(target, src, TF_POISON, 0) |
---|
3077 | ) { //Poison React |
---|
3078 | struct status_change_entry *sce = tsc->data[SC_POISONREACT]; |
---|
3079 | if (sstatus->def_ele == ELE_POISON) { |
---|
3080 | sce->val2 = 0; |
---|
3081 | skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); |
---|
3082 | } else { |
---|
3083 | skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); |
---|
3084 | --sce->val2; |
---|
3085 | } |
---|
3086 | if (sce->val2 <= 0) |
---|
3087 | status_change_end(target, SC_POISONREACT, -1); |
---|
3088 | } |
---|
3089 | } |
---|
3090 | map_freeblock_unlock(); |
---|
3091 | return wd.dmg_lv; |
---|
3092 | } |
---|
3093 | |
---|
3094 | //Begin custom Job (blackmagic) |
---|
3095 | int battle_check_living(int race,int element)// Living creature check [Brain] |
---|
3096 | { |
---|
3097 | if(element == ELE_UNDEAD || race == RC_UNDEAD // Undead element and race check |
---|
3098 | || race == RC_DEMON // Demon race check |
---|
3099 | || race == RC_FORMLESS // Formless race check |
---|
3100 | || element == ELE_GHOST){ // Ghost element check |
---|
3101 | return 0; |
---|
3102 | } |
---|
3103 | else { |
---|
3104 | return 1; |
---|
3105 | } |
---|
3106 | } |
---|
3107 | //end custom job |
---|
3108 | |
---|
3109 | int battle_check_undead(int race,int element) |
---|
3110 | { |
---|
3111 | if(battle_config.undead_detect_type == 0) { |
---|
3112 | if(element == ELE_UNDEAD) |
---|
3113 | return 1; |
---|
3114 | } |
---|
3115 | else if(battle_config.undead_detect_type == 1) { |
---|
3116 | if(race == RC_UNDEAD) |
---|
3117 | return 1; |
---|
3118 | } |
---|
3119 | else { |
---|
3120 | if(element == ELE_UNDEAD || race == RC_UNDEAD) |
---|
3121 | return 1; |
---|
3122 | } |
---|
3123 | return 0; |
---|
3124 | } |
---|
3125 | |
---|
3126 | //Returns the upmost level master starting with the given object |
---|
3127 | struct block_list* battle_get_master(struct block_list *src) |
---|
3128 | { |
---|
3129 | struct block_list *prev; //Used for infinite loop check (master of yourself?) |
---|
3130 | do { |
---|
3131 | prev = src; |
---|
3132 | switch (src->type) { |
---|
3133 | case BL_PET: |
---|
3134 | if (((TBL_PET*)src)->msd) |
---|
3135 | src = (struct block_list*)((TBL_PET*)src)->msd; |
---|
3136 | break; |
---|
3137 | case BL_MOB: |
---|
3138 | if (((TBL_MOB*)src)->master_id) |
---|
3139 | src = map_id2bl(((TBL_MOB*)src)->master_id); |
---|
3140 | break; |
---|
3141 | case BL_HOM: |
---|
3142 | if (((TBL_HOM*)src)->master) |
---|
3143 | src = (struct block_list*)((TBL_HOM*)src)->master; |
---|
3144 | break; |
---|
3145 | case BL_SKILL: |
---|
3146 | if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id) |
---|
3147 | src = map_id2bl(((TBL_SKILL*)src)->group->src_id); |
---|
3148 | break; |
---|
3149 | } |
---|
3150 | } while (src && src != prev); |
---|
3151 | return prev; |
---|
3152 | } |
---|
3153 | |
---|
3154 | /*========================================== |
---|
3155 | * Checks the state between two targets (rewritten by Skotlex) |
---|
3156 | * (enemy, friend, party, guild, etc) |
---|
3157 | * See battle.h for possible values/combinations |
---|
3158 | * to be used here (BCT_* constants) |
---|
3159 | * Return value is: |
---|
3160 | * 1: flag holds true (is enemy, party, etc) |
---|
3161 | * -1: flag fails |
---|
3162 | * 0: Invalid target (non-targetable ever) |
---|
3163 | *------------------------------------------*/ |
---|
3164 | int battle_check_target( struct block_list *src, struct block_list *target,int flag) |
---|
3165 | { |
---|
3166 | int m,state = 0; //Initial state none |
---|
3167 | int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally. |
---|
3168 | struct block_list *s_bl= src, *t_bl= target; |
---|
3169 | |
---|
3170 | nullpo_retr(0, src); |
---|
3171 | nullpo_retr(0, target); |
---|
3172 | |
---|
3173 | m = target->m; |
---|
3174 | if (flag&BCT_ENEMY && !map_flag_gvg(m) && !(status_get_mode(src)&MD_BOSS)) |
---|
3175 | { //No offensive stuff while in Basilica. |
---|
3176 | if (map_getcell(m,src->x,src->y,CELL_CHKBASILICA) || |
---|
3177 | map_getcell(m,target->x,target->y,CELL_CHKBASILICA)) |
---|
3178 | return -1; |
---|
3179 | } |
---|
3180 | |
---|
3181 | //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual |
---|
3182 | //objects involved. |
---|
3183 | if ((t_bl = battle_get_master(target)) == NULL) |
---|
3184 | t_bl = target; |
---|
3185 | |
---|
3186 | if ((s_bl = battle_get_master(src)) == NULL) |
---|
3187 | s_bl = src; |
---|
3188 | |
---|
3189 | switch (target->type) |
---|
3190 | { //Checks on actual target |
---|
3191 | case BL_PC: |
---|
3192 | if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target)) |
---|
3193 | return -1; //Cannot be targeted yet. |
---|
3194 | break; |
---|
3195 | case BL_MOB: |
---|
3196 | if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres |
---|
3197 | (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras |
---|
3198 | s_bl->type == BL_PC && src->type != BL_MOB) |
---|
3199 | { //Targettable by players |
---|
3200 | state |= BCT_ENEMY; |
---|
3201 | strip_enemy = 0; |
---|
3202 | } |
---|
3203 | break; |
---|
3204 | case BL_SKILL: |
---|
3205 | { |
---|
3206 | TBL_SKILL *su = (TBL_SKILL*)target; |
---|
3207 | if (!su->group) |
---|
3208 | return 0; |
---|
3209 | if (skill_get_inf2(su->group->skill_id)&INF2_TRAP) |
---|
3210 | { //Only a few skills can target traps... |
---|
3211 | switch (battle_getcurrentskill(src)) |
---|
3212 | { |
---|
3213 | case HT_REMOVETRAP: |
---|
3214 | case AC_SHOWER: |
---|
3215 | case WZ_SIGHTRASHER: |
---|
3216 | case WZ_SIGHTBLASTER: |
---|
3217 | case SM_MAGNUM: |
---|
3218 | state |= BCT_ENEMY; |
---|
3219 | strip_enemy = 0; |
---|
3220 | break; |
---|
3221 | default: |
---|
3222 | return 0; |
---|
3223 | } |
---|
3224 | } else if (su->group->skill_id==WZ_ICEWALL) |
---|
3225 | { |
---|
3226 | state |= BCT_ENEMY; |
---|
3227 | strip_enemy = 0; |
---|
3228 | } else //Excepting traps and icewall, you should not be able to target skills. |
---|
3229 | return 0; |
---|
3230 | } |
---|
3231 | break; |
---|
3232 | //Valid targets with no special checks here. |
---|
3233 | case BL_HOM: |
---|
3234 | break; |
---|
3235 | //All else not specified is an invalid target. |
---|
3236 | default: |
---|
3237 | return 0; |
---|
3238 | } |
---|
3239 | |
---|
3240 | switch (t_bl->type) |
---|
3241 | { //Checks on target master |
---|
3242 | case BL_PC: |
---|
3243 | { |
---|
3244 | TBL_PC *sd = (TBL_PC*)t_bl; |
---|
3245 | if (sd->status.karma && t_bl != s_bl && s_bl->type == BL_PC && |
---|
3246 | ((TBL_PC*)s_bl)->status.karma) |
---|
3247 | state |= BCT_ENEMY; //Characters with bad karma may fight amongst them. |
---|
3248 | if (sd->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY) |
---|
3249 | return 0; //Global inmunity to attacks. |
---|
3250 | if (sd->state.killable && t_bl != s_bl) |
---|
3251 | { |
---|
3252 | state |= BCT_ENEMY; //Universal Victim |
---|
3253 | strip_enemy = 0; |
---|
3254 | } |
---|
3255 | // Sketchy - begin |
---|
3256 | if (sd->state.god && t_bl != s_bl && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->state.demon && map[m].flag.hostile) { |
---|
3257 | state |= BCT_ENEMY; |
---|
3258 | strip_enemy = 0; |
---|
3259 | } |
---|
3260 | |
---|
3261 | if (sd->state.demon && t_bl != s_bl && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->state.god && map[m].flag.hostile) { |
---|
3262 | state |= BCT_ENEMY; |
---|
3263 | strip_enemy = 0; |
---|
3264 | } |
---|
3265 | // Sketchy -end |
---|
3266 | break; |
---|
3267 | } |
---|
3268 | case BL_MOB: |
---|
3269 | { |
---|
3270 | TBL_MOB *md = (TBL_MOB*)t_bl; |
---|
3271 | |
---|
3272 | if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id) |
---|
3273 | return 0; //Disable guardians/emperiums owned by Guilds on non-woe times. |
---|
3274 | |
---|
3275 | if( md->barricade && !md->barricade->killable ) |
---|
3276 | return 0; |
---|
3277 | break; |
---|
3278 | } |
---|
3279 | } |
---|
3280 | |
---|
3281 | switch(src->type) |
---|
3282 | { //Checks on actual src type |
---|
3283 | case BL_PET: |
---|
3284 | if (t_bl->type != BL_MOB && flag&BCT_ENEMY) |
---|
3285 | return 0; //Pet may not attack non-mobs. |
---|
3286 | if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY) |
---|
3287 | return 0; //pet may not attack Guardians/Emperium |
---|
3288 | break; |
---|
3289 | case BL_SKILL: |
---|
3290 | { |
---|
3291 | struct skill_unit *su = (struct skill_unit *)src; |
---|
3292 | if (!su->group) |
---|
3293 | return 0; |
---|
3294 | |
---|
3295 | if (su->group->src_id == target->id) |
---|
3296 | { |
---|
3297 | int inf2; |
---|
3298 | inf2 = skill_get_inf2(su->group->skill_id); |
---|
3299 | if (inf2&INF2_NO_TARGET_SELF) |
---|
3300 | return -1; |
---|
3301 | if (inf2&INF2_TARGET_SELF) |
---|
3302 | return 1; |
---|
3303 | } |
---|
3304 | break; |
---|
3305 | } |
---|
3306 | } |
---|
3307 | |
---|
3308 | switch (s_bl->type) |
---|
3309 | { //Checks on source master |
---|
3310 | case BL_PC: |
---|
3311 | { |
---|
3312 | TBL_PC *sd = (TBL_PC*) s_bl; |
---|
3313 | if( s_bl != t_bl ) |
---|
3314 | { |
---|
3315 | if( sd->state.killer ) |
---|
3316 | { |
---|
3317 | state |= BCT_ENEMY; //Is on a killing rampage :O |
---|
3318 | strip_enemy = 0; |
---|
3319 | } |
---|
3320 | else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) |
---|
3321 | { |
---|
3322 | if (t_bl->type == BL_PC && |
---|
3323 | (sd->duel_group == ((TBL_PC*)t_bl)->duel_group)) |
---|
3324 | //Duel targets can ONLY be your enemy, nothing else. |
---|
3325 | return (BCT_ENEMY&flag)?1:-1; |
---|
3326 | else // You can't target anything out of your duel |
---|
3327 | return 0; |
---|
3328 | } |
---|
3329 | } |
---|
3330 | if (map_flag_gvg(m) && !sd->status.guild_id && |
---|
3331 | t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data) |
---|
3332 | return 0; //If you don't belong to a guild, can't target guardians/emperium. |
---|
3333 | if (t_bl->type != BL_PC) |
---|
3334 | state |= BCT_ENEMY; //Natural enemy. |
---|
3335 | break; |
---|
3336 | } |
---|
3337 | case BL_MOB: |
---|
3338 | { |
---|
3339 | TBL_MOB*md = (TBL_MOB*)s_bl; |
---|
3340 | if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id) |
---|
3341 | return 0; //Disable guardians/emperium owned by Guilds on non-woe times. |
---|
3342 | if(md->state.killer/* || !(battle_config.mob_ai&0x400)*/) |
---|
3343 | state |= BCT_ENEMY; //By default everyone hates mobs. |
---|
3344 | else |
---|
3345 | { //Smart enemy criteria. |
---|
3346 | if (!md->special_state.ai) { //Normal mobs. |
---|
3347 | if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai) |
---|
3348 | state |= BCT_PARTY; //Normal mobs with no ai are friends. |
---|
3349 | else |
---|
3350 | state |= BCT_ENEMY; //However, all else are enemies. |
---|
3351 | } else { |
---|
3352 | if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai) |
---|
3353 | state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. |
---|
3354 | } |
---|
3355 | } |
---|
3356 | break; |
---|
3357 | } |
---|
3358 | default: |
---|
3359 | //Need some sort of default behaviour for unhandled types. |
---|
3360 | if (t_bl->type != s_bl->type) |
---|
3361 | state |= BCT_ENEMY; |
---|
3362 | break; |
---|
3363 | } |
---|
3364 | |
---|
3365 | if ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars |
---|
3366 | if (target->type&BL_CHAR) |
---|
3367 | return 1; |
---|
3368 | else |
---|
3369 | return -1; |
---|
3370 | } else |
---|
3371 | if (flag == BCT_NOONE) //Why would someone use this? no clue. |
---|
3372 | return -1; |
---|
3373 | |
---|
3374 | if (t_bl == s_bl) |
---|
3375 | { //No need for further testing. |
---|
3376 | state |= BCT_SELF|BCT_PARTY|BCT_GUILD; |
---|
3377 | if (state&BCT_ENEMY && strip_enemy) |
---|
3378 | state&=~BCT_ENEMY; |
---|
3379 | return (flag&state)?1:-1; |
---|
3380 | } |
---|
3381 | |
---|
3382 | if (map_flag_vs(m)) { //Check rivalry settings. |
---|
3383 | if (flag&(BCT_PARTY|BCT_ENEMY)) { |
---|
3384 | int s_party = status_get_party_id(s_bl); |
---|
3385 | if ( |
---|
3386 | !(map[m].flag.pvp && map[m].flag.pvp_noparty) && |
---|
3387 | !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && |
---|
3388 | s_party && s_party == status_get_party_id(t_bl) |
---|
3389 | ) |
---|
3390 | state |= BCT_PARTY; |
---|
3391 | else |
---|
3392 | state |= BCT_ENEMY; |
---|
3393 | } |
---|
3394 | if (flag&(BCT_GUILD|BCT_ENEMY)) { |
---|
3395 | int s_guild = status_get_guild_id(s_bl); |
---|
3396 | int t_guild = status_get_guild_id(t_bl); |
---|
3397 | if ( |
---|
3398 | !(map[m].flag.pvp && map[m].flag.pvp_noguild) && |
---|
3399 | s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) |
---|
3400 | ) |
---|
3401 | state |= BCT_GUILD; |
---|
3402 | else |
---|
3403 | state |= BCT_ENEMY; |
---|
3404 | } |
---|
3405 | if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && |
---|
3406 | s_bl->type == BL_PC && t_bl->type == BL_PC) |
---|
3407 | { //Prevent novice engagement on pk_mode (feature by Valaris) |
---|
3408 | TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl; |
---|
3409 | if ( |
---|
3410 | (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE || |
---|
3411 | (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE || |
---|
3412 | (int)sd->status.base_level < battle_config.pk_min_level || |
---|
3413 | (int)sd2->status.base_level < battle_config.pk_min_level || |
---|
3414 | (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range) |
---|
3415 | ) |
---|
3416 | state&=~BCT_ENEMY; |
---|
3417 | } |
---|
3418 | } else { //Non pvp/gvg, check party/guild settings. |
---|
3419 | if (flag&BCT_PARTY || state&BCT_ENEMY) { |
---|
3420 | int s_party = status_get_party_id(s_bl); |
---|
3421 | if(s_party && s_party == status_get_party_id(t_bl)) |
---|
3422 | state |= BCT_PARTY; |
---|
3423 | } |
---|
3424 | if (flag&BCT_GUILD || state&BCT_ENEMY) { |
---|
3425 | int s_guild = status_get_guild_id(s_bl); |
---|
3426 | int t_guild = status_get_guild_id(t_bl); |
---|
3427 | if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))) |
---|
3428 | state |= BCT_GUILD; |
---|
3429 | } |
---|
3430 | } |
---|
3431 | |
---|
3432 | if (!state) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. |
---|
3433 | state = BCT_NEUTRAL; |
---|
3434 | //Alliance state takes precedence over enemy one. |
---|
3435 | else if (state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD)) |
---|
3436 | state&=~BCT_ENEMY; |
---|
3437 | |
---|
3438 | return (flag&state)?1:-1; |
---|
3439 | } |
---|
3440 | /*========================================== |
---|
3441 | * Ëö»è |
---|
3442 | *------------------------------------------*/ |
---|
3443 | bool battle_check_range(struct block_list *src,struct block_list *bl,int range) |
---|
3444 | { |
---|
3445 | int d; |
---|
3446 | nullpo_retr(false, src); |
---|
3447 | nullpo_retr(false, bl); |
---|
3448 | |
---|
3449 | if(src->m != bl->m) // á€}bv |
---|
3450 | return false; |
---|
3451 | |
---|
3452 | if (!check_distance_bl(src, bl, range)) |
---|
3453 | return false; |
---|
3454 | |
---|
3455 | if((d=distance_bl(src, bl)) < 2) //No need for path checking. |
---|
3456 | return true; |
---|
3457 | |
---|
3458 | if (d> AREA_SIZE) |
---|
3459 | return false; //Avoid targetting objects beyond your range of sight. |
---|
3460 | |
---|
3461 | // ?áQš»è |
---|
3462 | return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); |
---|
3463 | } |
---|
3464 | |
---|
3465 | static const struct _battle_data { |
---|
3466 | const char* str; |
---|
3467 | int* val; |
---|
3468 | int defval; |
---|
3469 | int min; |
---|
3470 | int max; |
---|
3471 | } battle_data[] = { |
---|
3472 | { "warp_point_debug", &battle_config.warp_point_debug, 0, 0, 1, }, |
---|
3473 | { "enable_critical", &battle_config.enable_critical, BL_PC, BL_NUL, BL_ALL, }, |
---|
3474 | { "mob_critical_rate", &battle_config.mob_critical_rate, 100, 0, INT_MAX, }, |
---|
3475 | { "critical_rate", &battle_config.critical_rate, 100, 0, INT_MAX, }, |
---|
3476 | { "enable_baseatk", &battle_config.enable_baseatk, BL_PC|BL_HOM, BL_NUL, BL_ALL, }, |
---|
3477 | { "enable_perfect_flee", &battle_config.enable_perfect_flee, BL_PC|BL_PET, BL_NUL, BL_ALL, }, |
---|
3478 | { "casting_rate", &battle_config.cast_rate, 100, 0, INT_MAX, }, |
---|
3479 | { "delay_rate", &battle_config.delay_rate, 100, 0, INT_MAX, }, |
---|
3480 | { "delay_dependon_dex", &battle_config.delay_dependon_dex, 0, 0, 1, }, |
---|
3481 | { "delay_dependon_agi", &battle_config.delay_dependon_agi, 0, 0, 1, }, |
---|
3482 | { "skill_delay_attack_enable", &battle_config.sdelay_attack_enable, 0, 0, 1, }, |
---|
3483 | { "left_cardfix_to_right", &battle_config.left_cardfix_to_right, 0, 0, 1, }, |
---|
3484 | { "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, }, |
---|
3485 | { "skill_out_range_consume", &battle_config.skill_out_range_consume, 1, 0, 1, }, |
---|
3486 | { "skillrange_by_distance", &battle_config.skillrange_by_distance, ~BL_PC, BL_NUL, BL_ALL, }, |
---|
3487 | { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, ~BL_PC, BL_NUL, BL_ALL, }, |
---|
3488 | { "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, }, |
---|
3489 | { "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, }, |
---|
3490 | { "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, }, |
---|
3491 | { "traps_setting", &battle_config.traps_setting, 0, 0, 1, }, |
---|
3492 | { "summon_flora_setting", &battle_config.summon_flora, 1|2, 0, 1|2, }, |
---|
3493 | { "clear_skills_on_death", &battle_config.clear_unit_ondeath, BL_NUL, BL_NUL, BL_ALL, }, |
---|
3494 | { "clear_skills_on_warp", &battle_config.clear_unit_onwarp, BL_ALL, BL_NUL, BL_ALL, }, |
---|
3495 | { "random_monster_checklv", &battle_config.random_monster_checklv, 1, 0, 1, }, |
---|
3496 | { "attribute_recover", &battle_config.attr_recover, 1, 0, 1, }, |
---|
3497 | { "flooritem_lifetime", &battle_config.flooritem_lifetime, 60000, 1000, INT_MAX, }, |
---|
3498 | { "item_auto_get", &battle_config.item_auto_get, 0, 0, 1, }, |
---|
3499 | { "item_first_get_time", &battle_config.item_first_get_time, 3000, 0, INT_MAX, }, |
---|
3500 | { "item_second_get_time", &battle_config.item_second_get_time, 1000, 0, INT_MAX, }, |
---|
3501 | { "item_third_get_time", &battle_config.item_third_get_time, 1000, 0, INT_MAX, }, |
---|
3502 | { "mvp_item_first_get_time", &battle_config.mvp_item_first_get_time, 10000, 0, INT_MAX, }, |
---|
3503 | { "mvp_item_second_get_time", &battle_config.mvp_item_second_get_time, 10000, 0, INT_MAX, }, |
---|
3504 | { "mvp_item_third_get_time", &battle_config.mvp_item_third_get_time, 2000, 0, INT_MAX, }, |
---|
3505 | { "drop_rate0item", &battle_config.drop_rate0item, 0, 0, 1, }, |
---|
3506 | { "base_exp_rate", &battle_config.base_exp_rate, 100, 0, INT_MAX, }, |
---|
3507 | { "job_exp_rate", &battle_config.job_exp_rate, 100, 0, INT_MAX, }, |
---|
3508 | { "pvp_exp", &battle_config.pvp_exp, 1, 0, 1, }, |
---|
3509 | { "death_penalty_type", &battle_config.death_penalty_type, 0, 0, 2, }, |
---|
3510 | { "death_penalty_base", &battle_config.death_penalty_base, 0, 0, INT_MAX, }, |
---|
3511 | { "death_penalty_job", &battle_config.death_penalty_job, 0, 0, INT_MAX, }, |
---|
3512 | { "zeny_penalty", &battle_config.zeny_penalty, 0, 0, INT_MAX, }, |
---|
3513 | { "hp_rate", &battle_config.hp_rate, 100, 1, INT_MAX, }, |
---|
3514 | { "sp_rate", &battle_config.sp_rate, 100, 1, INT_MAX, }, |
---|
3515 | { "restart_hp_rate", &battle_config.restart_hp_rate, 0, 0, 100, }, |
---|
3516 | { "restart_sp_rate", &battle_config.restart_sp_rate, 0, 0, 100, }, |
---|
3517 | { "guild_aura", &battle_config.guild_aura, 31, 0, 31, }, |
---|
3518 | { "mvp_hp_rate", &battle_config.mvp_hp_rate, 100, 1, INT_MAX, }, |
---|
3519 | { "mvp_exp_rate", &battle_config.mvp_exp_rate, 100, 0, INT_MAX, }, |
---|
3520 | { "monster_hp_rate", &battle_config.monster_hp_rate, 100, 1, INT_MAX, }, |
---|
3521 | { "monster_max_aspd", &battle_config.monster_max_aspd, 199, 100, 199, }, |
---|
3522 | { "view_range_rate", &battle_config.view_range_rate, 100, 0, INT_MAX, }, |
---|
3523 | { "chase_range_rate", &battle_config.chase_range_rate, 100, 0, INT_MAX, }, |
---|
3524 | { "gtb_sc_immunity", &battle_config.gtb_sc_immunity, 50, 0, INT_MAX, }, |
---|
3525 | { "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, }, |
---|
3526 | { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, }, |
---|
3527 | { "emergency_call", &battle_config.emergency_call, 11, 0, 31, }, |
---|
3528 | { "atcommand_gm_only", &battle_config.atc_gmonly, 0, 0, 1, }, |
---|
3529 | { "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, }, |
---|
3530 | { "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, }, |
---|
3531 | { "partial_name_scan", &battle_config.partial_name_scan, 0, 0, 1, }, |
---|
3532 | { "gm_all_skill", &battle_config.gm_allskill, 0, 0, 100, }, |
---|
3533 | { "gm_all_equipment", &battle_config.gm_allequip, 0, 0, 100, }, |
---|
3534 | { "gm_skill_unconditional", &battle_config.gm_skilluncond, 0, 0, 100, }, |
---|
3535 | { "gm_join_chat", &battle_config.gm_join_chat, 0, 0, 100, }, |
---|
3536 | { "gm_kick_chat", &battle_config.gm_kick_chat, 0, 0, 100, }, |
---|
3537 | { "player_skillfree", &battle_config.skillfree, 0, 0, 1, }, |
---|
3538 | { "player_skillup_limit", &battle_config.skillup_limit, 1, 0, 1, }, |
---|
3539 | { "weapon_produce_rate", &battle_config.wp_rate, 100, 0, INT_MAX, }, |
---|
3540 | { "potion_produce_rate", &battle_config.pp_rate, 100, 0, INT_MAX, }, |
---|
3541 | { "monster_active_enable", &battle_config.monster_active_enable, 1, 0, 1, }, |
---|
3542 | { "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate, 100, 0, INT_MAX, }, |
---|
3543 | { "monster_loot_type", &battle_config.monster_loot_type, 0, 0, 1, }, |
---|
3544 | // { "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated |
---|
3545 | { "mob_skill_rate", &battle_config.mob_skill_rate, 100, 0, INT_MAX, }, |
---|
3546 | { "mob_skill_delay", &battle_config.mob_skill_delay, 100, 0, INT_MAX, }, |
---|
3547 | { "mob_count_rate", &battle_config.mob_count_rate, 100, 0, INT_MAX, }, |
---|
3548 | { "mob_spawn_delay", &battle_config.mob_spawn_delay, 100, 0, INT_MAX, }, |
---|
3549 | { "plant_spawn_delay", &battle_config.plant_spawn_delay, 100, 0, INT_MAX, }, |
---|
3550 | { "boss_spawn_delay", &battle_config.boss_spawn_delay, 100, 0, INT_MAX, }, |
---|
3551 | { "no_spawn_on_player", &battle_config.no_spawn_on_player, 0, 0, 100, }, |
---|
3552 | { "force_random_spawn", &battle_config.force_random_spawn, 0, 0, 1, }, |
---|
3553 | { "slaves_inherit_mode", &battle_config.slaves_inherit_mode, 2, 0, 3, }, |
---|
3554 | { "slaves_inherit_speed", &battle_config.slaves_inherit_speed, 3, 0, 3, }, |
---|
3555 | { "summons_trigger_autospells", &battle_config.summons_trigger_autospells, 1, 0, 1, }, |
---|
3556 | { "pc_damage_walk_delay_rate", &battle_config.pc_walk_delay_rate, 20, 0, INT_MAX, }, |
---|
3557 | { "damage_walk_delay_rate", &battle_config.walk_delay_rate, 100, 0, INT_MAX, }, |
---|
3558 | { "multihit_delay", &battle_config.multihit_delay, 80, 0, INT_MAX, }, |
---|
3559 | { "quest_skill_learn", &battle_config.quest_skill_learn, 0, 0, 1, }, |
---|
3560 | { "quest_skill_reset", &battle_config.quest_skill_reset, 0, 0, 1, }, |
---|
3561 | { "basic_skill_check", &battle_config.basic_skill_check, 1, 0, 1, }, |
---|
3562 | { "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, }, |
---|
3563 | { "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, }, |
---|
3564 | { "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, }, |
---|
3565 | { "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, }, |
---|
3566 | { "pet_rename", &battle_config.pet_rename, 0, 0, 1, }, |
---|
3567 | { "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, }, |
---|
3568 | { "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, }, |
---|
3569 | { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, }, |
---|
3570 | { "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, }, |
---|
3571 | { "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, }, |
---|
3572 | { "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, }, |
---|
3573 | { "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, }, |
---|
3574 | { "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, }, |
---|
3575 | { "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, }, |
---|
3576 | { "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, }, |
---|
3577 | { "pet_lv_rate", &battle_config.pet_lv_rate, 0, 0, INT_MAX, }, |
---|
3578 | { "pet_max_stats", &battle_config.pet_max_stats, 99, 0, INT_MAX, }, |
---|
3579 | { "pet_max_atk1", &battle_config.pet_max_atk1, 750, 0, INT_MAX, }, |
---|
3580 | { "pet_max_atk2", &battle_config.pet_max_atk2, 1000, 0, INT_MAX, }, |
---|
3581 | { "pet_disable_in_gvg", &battle_config.pet_no_gvg, 0, 0, 1, }, |
---|
3582 | { "skill_min_damage", &battle_config.skill_min_damage, 2|4, 0, 1|2|4, }, |
---|
3583 | { "finger_offensive_type", &battle_config.finger_offensive_type, 0, 0, 1, }, |
---|
3584 | { "heal_exp", &battle_config.heal_exp, 0, 0, INT_MAX, }, |
---|
3585 | { "resurrection_exp", &battle_config.resurrection_exp, 0, 0, INT_MAX, }, |
---|
3586 | { "shop_exp", &battle_config.shop_exp, 0, 0, INT_MAX, }, |
---|
3587 | { "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, }, |
---|
3588 | { "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, }, |
---|
3589 | { "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, }, |
---|
3590 | { "item_check", &battle_config.item_check, 0, 0, 1, }, |
---|
3591 | { "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, }, |
---|
3592 | { "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, }, |
---|
3593 | { "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, }, |
---|
3594 | { "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, }, |
---|
3595 | { "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, }, |
---|
3596 | { "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, }, |
---|
3597 | { "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, }, |
---|
3598 | { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, }, |
---|
3599 | { "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate, 50, 50, 101 }, |
---|
3600 | { "arrow_decrement", &battle_config.arrow_decrement, 1, 0, 2, }, |
---|
3601 | { "max_aspd", &battle_config.max_aspd, 199, 100, 199, }, |
---|
3602 | { "max_walk_speed", &battle_config.max_walk_speed, 300, 100, 100*DEFAULT_WALK_SPEED, }, |
---|
3603 | { "max_lv", &battle_config.max_lv, 99, 0, 127, }, |
---|
3604 | { "aura_lv", &battle_config.aura_lv, 99, 0, INT_MAX, }, |
---|
3605 | { "max_hp", &battle_config.max_hp, 32500, 100, 1000000000, }, |
---|
3606 | { "max_sp", &battle_config.max_sp, 32500, 100, 1000000000, }, |
---|
3607 | { "max_cart_weight", &battle_config.max_cart_weight, 8000, 100, 1000000, }, |
---|
3608 | { "max_parameter", &battle_config.max_parameter, 99, 10, 10000, }, |
---|
3609 | { "max_baby_parameter", &battle_config.max_baby_parameter, 80, 10, 10000, }, |
---|
3610 | { "max_def", &battle_config.max_def, 99, 0, INT_MAX, }, |
---|
3611 | { "over_def_bonus", &battle_config.over_def_bonus, 0, 0, 1000, }, |
---|
3612 | { "skill_log", &battle_config.skill_log, BL_NUL, BL_NUL, BL_ALL, }, |
---|
3613 | { "battle_log", &battle_config.battle_log, 0, 0, 1, }, |
---|
3614 | { "save_log", &battle_config.save_log, 0, 0, 1, }, |
---|
3615 | { "etc_log", &battle_config.etc_log, 1, 0, 1, }, |
---|
3616 | { "save_clothcolor", &battle_config.save_clothcolor, 1, 0, 1, }, |
---|
3617 | { "undead_detect_type", &battle_config.undead_detect_type, 0, 0, 2, }, |
---|
3618 | { "auto_counter_type", &battle_config.auto_counter_type, BL_ALL, BL_NUL, BL_ALL, }, |
---|
3619 | { "min_hitrate", &battle_config.min_hitrate, 5, 0, 100, }, |
---|
3620 | { "max_hitrate", &battle_config.max_hitrate, 100, 0, 100, }, |
---|
3621 | { "agi_penalty_target", &battle_config.agi_penalty_target, BL_PC, BL_NUL, BL_ALL, }, |
---|
3622 | { "agi_penalty_type", &battle_config.agi_penalty_type, 1, 0, 2, }, |
---|
3623 | { "agi_penalty_count", &battle_config.agi_penalty_count, 3, 2, INT_MAX, }, |
---|
3624 | { "agi_penalty_num", &battle_config.agi_penalty_num, 10, 0, INT_MAX, }, |
---|
3625 | { "agi_penalty_count_lv", &battle_config.agi_penalty_count_lv, ATK_FLEE, 0, INT_MAX, }, |
---|
3626 | { "vit_penalty_target", &battle_config.vit_penalty_target, BL_PC, BL_NUL, BL_ALL, }, |
---|
3627 | { "vit_penalty_type", &battle_config.vit_penalty_type, 1, 0, 2, }, |
---|
3628 | { "vit_penalty_count", &battle_config.vit_penalty_count, 3, 2, INT_MAX, }, |
---|
3629 | { "vit_penalty_num", &battle_config.vit_penalty_num, 5, 0, INT_MAX, }, |
---|
3630 | { "vit_penalty_count_lv", &battle_config.vit_penalty_count_lv, ATK_DEF, 0, INT_MAX, }, |
---|
3631 | { "weapon_defense_type", &battle_config.weapon_defense_type, 0, 0, INT_MAX, }, |
---|
3632 | { "magic_defense_type", &battle_config.magic_defense_type, 0, 0, INT_MAX, }, |
---|
3633 | { "skill_reiteration", &battle_config.skill_reiteration, BL_NUL, BL_NUL, BL_ALL, }, |
---|
3634 | { "skill_nofootset", &battle_config.skill_nofootset, BL_PC, BL_NUL, BL_ALL, }, |
---|
3635 | { "player_cloak_check_type", &battle_config.pc_cloak_check_type, 1, 0, 1|2|4, }, |
---|
3636 | { "monster_cloak_check_type", &battle_config.monster_cloak_check_type, 4, 0, 1|2|4, }, |
---|
3637 | { "sense_type", &battle_config.estimation_type, 1|2, 0, 1|2, }, |
---|
3638 | { "gvg_eliminate_time", &battle_config.gvg_eliminate_time, 7000, 0, INT_MAX, }, |
---|
3639 | { "gvg_short_attack_damage_rate", &battle_config.gvg_short_damage_rate, 80, 0, INT_MAX, }, |
---|
3640 | { "gvg_long_attack_damage_rate", &battle_config.gvg_long_damage_rate, 80, 0, INT_MAX, }, |
---|
3641 | { "gvg_weapon_attack_damage_rate", &battle_config.gvg_weapon_damage_rate, 60, 0, INT_MAX, }, |
---|
3642 | { "gvg_magic_attack_damage_rate", &battle_config.gvg_magic_damage_rate, 60, 0, INT_MAX, }, |
---|
3643 | { "gvg_misc_attack_damage_rate", &battle_config.gvg_misc_damage_rate, 60, 0, INT_MAX, }, |
---|
3644 | { "gvg_flee_penalty", &battle_config.gvg_flee_penalty, 20, 0, INT_MAX, }, |
---|
3645 | { "pk_short_attack_damage_rate", &battle_config.pk_short_damage_rate, 80, 0, INT_MAX, }, |
---|
3646 | { "pk_long_attack_damage_rate", &battle_config.pk_long_damage_rate, 70, 0, INT_MAX, }, |
---|
3647 | { "pk_weapon_attack_damage_rate", &battle_config.pk_weapon_damage_rate, 60, 0, INT_MAX, }, |
---|
3648 | { "pk_magic_attack_damage_rate", &battle_config.pk_magic_damage_rate, 60, 0, INT_MAX, }, |
---|
3649 | { "pk_misc_attack_damage_rate", &battle_config.pk_misc_damage_rate, 60, 0, INT_MAX, }, |
---|
3650 | { "mob_changetarget_byskill", &battle_config.mob_changetarget_byskill, 0, 0, 1, }, |
---|
3651 | { "attack_direction_change", &battle_config.attack_direction_change, BL_ALL, BL_NUL, BL_ALL, }, |
---|
3652 | { "land_skill_limit", &battle_config.land_skill_limit, BL_ALL, BL_NUL, BL_ALL, }, |
---|
3653 | { "monster_class_change_full_recover", &battle_config.monster_class_change_recover, 1, 0, 1, }, |
---|
3654 | { "produce_item_name_input", &battle_config.produce_item_name_input, 0x1|0x2, 0, 0x9F, }, |
---|
3655 | { "display_skill_fail", &battle_config.display_skill_fail, 2, 0, 1|2|4|8, }, |
---|
3656 | { "chat_warpportal", &battle_config.chat_warpportal, 0, 0, 1, }, |
---|
3657 | { "mob_warp", &battle_config.mob_warp, 0, 0, 1|2|4, }, |
---|
3658 | { "dead_branch_active", &battle_config.dead_branch_active, 1, 0, 1, }, |
---|
3659 | { "vending_max_value", &battle_config.vending_max_value, 10000000, 1, MAX_ZENY, }, |
---|
3660 | { "vending_over_max", &battle_config.vending_over_max, 1, 0, 1, }, |
---|
3661 | { "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, }, |
---|
3662 | { "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, }, |
---|
3663 | { "show_party_share_picker", &battle_config.party_show_share_picker, 0, 0, 1, }, |
---|
3664 | { "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, }, |
---|
3665 | { "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3, }, |
---|
3666 | { "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, }, |
---|
3667 | { "gx_allhit", &battle_config.gx_allhit, 0, 0, 1, }, |
---|
3668 | { "gx_disptype", &battle_config.gx_disptype, 1, 0, 1, }, |
---|
3669 | { "devotion_level_difference", &battle_config.devotion_level_difference, 10, 0, INT_MAX, }, |
---|
3670 | { "player_skill_partner_check", &battle_config.player_skill_partner_check, 1, 0, 1, }, |
---|
3671 | { "hide_GM_session", &battle_config.hide_GM_session, 0, 0, 1, }, |
---|
3672 | { "invite_request_check", &battle_config.invite_request_check, 1, 0, 1, }, |
---|
3673 | { "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, }, |
---|
3674 | { "disp_experience", &battle_config.disp_experience, 0, 0, 1, }, |
---|
3675 | { "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, }, |
---|
3676 | { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, }, |
---|
3677 | { "gm_cant_drop_min_lv", &battle_config.gm_cant_drop_min_lv, 1, 0, 100, }, |
---|
3678 | { "gm_cant_drop_max_lv", &battle_config.gm_cant_drop_max_lv, 0, 0, 100, }, |
---|
3679 | { "disp_hpmeter", &battle_config.disp_hpmeter, 0, 0, 100, }, |
---|
3680 | { "bone_drop", &battle_config.bone_drop, 0, 0, 2, }, |
---|
3681 | { "buyer_name", &battle_config.buyer_name, 1, 0, 1, }, |
---|
3682 | { "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, }, |
---|
3683 | { "cell_stack_limit", &battle_config.cell_stack_limit, 1, 1, 255, }, |
---|
3684 | // eAthena additions |
---|
3685 | { "item_logarithmic_drops", &battle_config.logarithmic_drops, 0, 0, 1, }, |
---|
3686 | { "item_drop_common_min", &battle_config.item_drop_common_min, 1, 1, 10000, }, |
---|
3687 | { "item_drop_common_max", &battle_config.item_drop_common_max, 10000, 1, 10000, }, |
---|
3688 | { "item_drop_equip_min", &battle_config.item_drop_equip_min, 1, 1, 10000, }, |
---|
3689 | { "item_drop_equip_max", &battle_config.item_drop_equip_max, 10000, 1, 10000, }, |
---|
3690 | { "item_drop_card_min", &battle_config.item_drop_card_min, 1, 1, 10000, }, |
---|
3691 | { "item_drop_card_max", &battle_config.item_drop_card_max, 10000, 1, 10000, }, |
---|
3692 | { "item_drop_mvp_min", &battle_config.item_drop_mvp_min, 1, 1, 10000, }, |
---|
3693 | { "item_drop_mvp_max", &battle_config.item_drop_mvp_max, 10000, 1, 10000, }, |
---|
3694 | { "item_drop_heal_min", &battle_config.item_drop_heal_min, 1, 1, 10000, }, |
---|
3695 | { "item_drop_heal_max", &battle_config.item_drop_heal_max, 10000, 1, 10000, }, |
---|
3696 | { "item_drop_use_min", &battle_config.item_drop_use_min, 1, 1, 10000, }, |
---|
3697 | { "item_drop_use_max", &battle_config.item_drop_use_max, 10000, 1, 10000, }, |
---|
3698 | { "item_drop_add_min", &battle_config.item_drop_adddrop_min, 1, 1, 10000, }, |
---|
3699 | { "item_drop_add_max", &battle_config.item_drop_adddrop_max, 10000, 1, 10000, }, |
---|
3700 | { "item_drop_treasure_min", &battle_config.item_drop_treasure_min, 1, 1, 10000, }, |
---|
3701 | { "item_drop_treasure_max", &battle_config.item_drop_treasure_max, 10000, 1, 10000, }, |
---|
3702 | { "item_rate_mvp", &battle_config.item_rate_mvp, 100, 0, 1000000, }, |
---|
3703 | { "item_rate_common", &battle_config.item_rate_common, 100, 0, 1000000, }, |
---|
3704 | { "item_rate_common_boss", &battle_config.item_rate_common_boss, 100, 0, 1000000, }, |
---|
3705 | { "item_rate_equip", &battle_config.item_rate_equip, 100, 0, 1000000, }, |
---|
3706 | { "item_rate_equip_boss", &battle_config.item_rate_equip_boss, 100, 0, 1000000, }, |
---|
3707 | { "item_rate_card", &battle_config.item_rate_card, 100, 0, 1000000, }, |
---|
3708 | { "item_rate_card_boss", &battle_config.item_rate_card_boss, 100, 0, 1000000, }, |
---|
3709 | { "item_rate_heal", &battle_config.item_rate_heal, 100, 0, 1000000, }, |
---|
3710 | { "item_rate_heal_boss", &battle_config.item_rate_heal_boss, 100, 0, 1000000, }, |
---|
3711 | { "item_rate_use", &battle_config.item_rate_use, 100, 0, 1000000, }, |
---|
3712 | { "item_rate_use_boss", &battle_config.item_rate_use_boss, 100, 0, 1000000, }, |
---|
3713 | { "item_rate_adddrop", &battle_config.item_rate_adddrop, 100, 0, 1000000, }, |
---|
3714 | { "item_rate_treasure", &battle_config.item_rate_treasure, 100, 0, 1000000, }, |
---|
3715 | { "prevent_logout", &battle_config.prevent_logout, 10000, 0, 60000, }, |
---|
3716 | { "alchemist_summon_reward", &battle_config.alchemist_summon_reward, 1, 0, 2, }, |
---|
3717 | { "drops_by_luk", &battle_config.drops_by_luk, 0, 0, INT_MAX, }, |
---|
3718 | { "drops_by_luk2", &battle_config.drops_by_luk2, 0, 0, INT_MAX, }, |
---|
3719 | { "equip_natural_break_rate", &battle_config.equip_natural_break_rate, 0, 0, INT_MAX, }, |
---|
3720 | { "equip_self_break_rate", &battle_config.equip_self_break_rate, 100, 0, INT_MAX, }, |
---|
3721 | { "equip_skill_break_rate", &battle_config.equip_skill_break_rate, 100, 0, INT_MAX, }, |
---|
3722 | { "pk_mode", &battle_config.pk_mode, 0, 0, 1, }, |
---|
3723 | { "pk_level_range", &battle_config.pk_level_range, 0, 0, INT_MAX, }, |
---|
3724 | { "manner_system", &battle_config.manner_system, 0xFFF, 0, 0xFFF, }, |
---|
3725 | { "pet_equip_required", &battle_config.pet_equip_required, 0, 0, 1, }, |
---|
3726 | { "multi_level_up", &battle_config.multi_level_up, 0, 0, 1, }, |
---|
3727 | { "max_exp_gain_rate", &battle_config.max_exp_gain_rate, 0, 0, INT_MAX, }, |
---|
3728 | { "backstab_bow_penalty", &battle_config.backstab_bow_penalty, 0, 0, 1, }, |
---|
3729 | { "night_at_start", &battle_config.night_at_start, 0, 0, 1, }, |
---|
3730 | { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, }, |
---|
3731 | { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, }, |
---|
3732 | { "hack_info_GM_level", &battle_config.hack_info_GM_level, 60, 0, 100, }, |
---|
3733 | { "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level, 20, 0, 100, }, |
---|
3734 | { "who_display_aid", &battle_config.who_display_aid, 40, 0, 100, }, |
---|
3735 | { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFF, 0x0000, 0xFFFF, }, |
---|
3736 | { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, }, |
---|
3737 | { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, }, |
---|
3738 | { "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, }, |
---|
3739 | { "max_hair_color", &battle_config.max_hair_color, 9, 0, INT_MAX, }, |
---|
3740 | { "min_cloth_color", &battle_config.min_cloth_color, 0, 0, INT_MAX, }, |
---|
3741 | { "max_cloth_color", &battle_config.max_cloth_color, 4, 0, INT_MAX, }, |
---|
3742 | { "pet_hair_style", &battle_config.pet_hair_style, 100, 0, INT_MAX, }, |
---|
3743 | { "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, }, |
---|
3744 | { "area_size", &battle_config.area_size, 14, 0, INT_MAX, }, |
---|
3745 | { "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, }, |
---|
3746 | { "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, }, |
---|
3747 | { "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, }, |
---|
3748 | { "pk_min_level", &battle_config.pk_min_level, 55, 1, INT_MAX, }, |
---|
3749 | { "skill_steal_max_tries", &battle_config.skill_steal_max_tries, 0, 0, UCHAR_MAX, }, |
---|
3750 | { "motd_type", &battle_config.motd_type, 0, 0, 1, }, |
---|
3751 | { "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, }, |
---|
3752 | { "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, }, |
---|
3753 | { "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, }, |
---|
3754 | { "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, }, |
---|
3755 | { "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, }, |
---|
3756 | { "default_walk_delay", &battle_config.default_walk_delay, 300, 0, INT_MAX, }, |
---|
3757 | { "no_skill_delay", &battle_config.no_skill_delay, BL_MOB, BL_NUL, BL_ALL, }, |
---|
3758 | { "attack_walk_delay", &battle_config.attack_walk_delay, BL_ALL, BL_NUL, BL_ALL, }, |
---|
3759 | { "require_glory_guild", &battle_config.require_glory_guild, 0, 0, 1, }, |
---|
3760 | { "idle_no_share", &battle_config.idle_no_share, 0, 0, INT_MAX, }, |
---|
3761 | { "party_even_share_bonus", &battle_config.party_even_share_bonus, 0, 0, INT_MAX, }, |
---|
3762 | { "delay_battle_damage", &battle_config.delay_battle_damage, 1, 0, 1, }, |
---|
3763 | { "hide_woe_damage", &battle_config.hide_woe_damage, 0, 0, 1, }, |
---|
3764 | { "display_version", &battle_config.display_version, 1, 0, 1, }, |
---|
3765 | { "display_hallucination", &battle_config.display_hallucination, 1, 0, 1, }, |
---|
3766 | { "use_statpoint_table", &battle_config.use_statpoint_table, 1, 0, 1, }, |
---|
3767 | { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, }, |
---|
3768 | { "copyskill_restrict", &battle_config.copyskill_restrict, 2, 0, 2, }, |
---|
3769 | { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, }, |
---|
3770 | { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, }, |
---|
3771 | { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, }, |
---|
3772 | { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, }, |
---|
3773 | { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, }, |
---|
3774 | { "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, }, |
---|
3775 | { "show_hp_sp_drain", &battle_config.show_hp_sp_drain, 0, 0, 1, }, |
---|
3776 | { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, }, |
---|
3777 | { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, }, |
---|
3778 | { "mob_clear_delay", &battle_config.mob_clear_delay, 0, 0, INT_MAX, }, |
---|
3779 | { "character_size", &battle_config.character_size, 1|2, 0, 1|2, }, |
---|
3780 | { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, |
---|
3781 | { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, |
---|
3782 | { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, |
---|
3783 | { "title_lvl1", &battle_config.title_lvl1, 1, 0, 100, }, |
---|
3784 | { "title_lvl2", &battle_config.title_lvl2, 10, 0, 100, }, |
---|
3785 | { "title_lvl3", &battle_config.title_lvl3, 20, 0, 100, }, |
---|
3786 | { "title_lvl4", &battle_config.title_lvl4, 40, 0, 100, }, |
---|
3787 | { "title_lvl5", &battle_config.title_lvl5, 50, 0, 100, }, |
---|
3788 | { "title_lvl6", &battle_config.title_lvl6, 60, 0, 100, }, |
---|
3789 | { "title_lvl7", &battle_config.title_lvl7, 80, 0, 100, }, |
---|
3790 | { "title_lvl8", &battle_config.title_lvl8, 99, 0, 100, }, |
---|
3791 | { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, |
---|
3792 | { "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, }, |
---|
3793 | { "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, }, |
---|
3794 | { "duel_autoleave_when_die", &battle_config.duel_autoleave_when_die, 1, 0, 1, }, |
---|
3795 | { "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, }, |
---|
3796 | { "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, }, |
---|
3797 | { "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, }, |
---|
3798 | { "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, }, |
---|
3799 | { "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, }, |
---|
3800 | { "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, }, |
---|
3801 | { "status_cast_cancel", &battle_config.sc_castcancel, BL_NUL, BL_NUL, BL_ALL, }, |
---|
3802 | { "pc_status_def_rate", &battle_config.pc_sc_def_rate, 100, 0, INT_MAX, }, |
---|
3803 | { "mob_status_def_rate", &battle_config.mob_sc_def_rate, 100, 0, INT_MAX, }, |
---|
3804 | { "pc_luk_status_def", &battle_config.pc_luk_sc_def, 300, 1, INT_MAX, }, |
---|
3805 | { "mob_luk_status_def", &battle_config.mob_luk_sc_def, 300, 1, INT_MAX, }, |
---|
3806 | { "pc_max_status_def", &battle_config.pc_max_sc_def, 100, 0, INT_MAX, }, |
---|
3807 | { "mob_max_status_def", &battle_config.mob_max_sc_def, 100, 0, INT_MAX, }, |
---|
3808 | { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio, 1, 0, 10000, }, |
---|
3809 | { "sg_angel_skill_ratio", &battle_config.sg_angel_skill_ratio, 10, 0, 10000, }, |
---|
3810 | { "autospell_stacking", &battle_config.autospell_stacking, 0, 0, 1, }, |
---|
3811 | { "override_mob_names", &battle_config.override_mob_names, 0, 0, 2, }, |
---|
3812 | { "min_chat_delay", &battle_config.min_chat_delay, 0, 0, INT_MAX, }, |
---|
3813 | { "friend_auto_add", &battle_config.friend_auto_add, 1, 0, 1, }, |
---|
3814 | { "hom_rename", &battle_config.hom_rename, 0, 0, 1, }, |
---|
3815 | { "homunculus_show_growth", &battle_config.homunculus_show_growth, 0, 0, 1, }, |
---|
3816 | { "homunculus_friendly_rate", &battle_config.homunculus_friendly_rate, 100, 0, INT_MAX, }, |
---|
3817 | { "vending_tax", &battle_config.vending_tax, 0, 0, 10000, }, |
---|
3818 | { "day_duration", &battle_config.day_duration, 0, 0, INT_MAX, }, |
---|
3819 | { "night_duration", &battle_config.night_duration, 0, 0, INT_MAX, }, |
---|
3820 | { "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, }, |
---|
3821 | { "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, }, |
---|
3822 | { "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, }, |
---|
3823 | { "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, }, |
---|
3824 | { "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, }, |
---|
3825 | { "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, }, |
---|
3826 | { "at_mapflag", &battle_config.autotrade_mapflag, 0, 0, 1, }, |
---|
3827 | { "at_timeout", &battle_config.at_timeout, 0, 0, INT_MAX, }, |
---|
3828 | { "homunculus_autoloot", &battle_config.homunculus_autoloot, 0, 0, 1, }, |
---|
3829 | { "idle_no_autoloot", &battle_config.idle_no_autoloot, 0, 0, INT_MAX, }, |
---|
3830 | { "max_guild_alliance", &battle_config.max_guild_alliance, 3, 1, 3, }, |
---|
3831 | { "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, }, |
---|
3832 | { "auction_feeperhour", &battle_config.auction_feeperhour, 12000, 0, INT_MAX, }, |
---|
3833 | { "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, }, |
---|
3834 | //Begin Custom Job (blackmagic) |
---|
3835 | //Vanaheim battle settings [Brainstorm] |
---|
3836 | { "necro_retaliation", &battle_config.necro_retaliation, 1, 0, 1, }, |
---|
3837 | { "disp_summon_stats", &battle_config.disp_summon_stats, |
---|
3838 | //End Custom Job |
---|
3839 | { "gm_viewequip_min_lv", &battle_config.gm_viewequip_min_lv, 0, 0, 99, }, |
---|
3840 | }; |
---|
3841 | |
---|
3842 | |
---|
3843 | int battle_set_value(const char* w1, const char* w2) |
---|
3844 | { |
---|
3845 | int val = config_switch(w2); |
---|
3846 | |
---|
3847 | int i; |
---|
3848 | ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); |
---|
3849 | if (i == ARRAYLENGTH(battle_data)) |
---|
3850 | return 0; // not found |
---|
3851 | |
---|
3852 | if (val < battle_data[i].min || val > battle_data[i].max) |
---|
3853 | { |
---|
3854 | ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval); |
---|
3855 | val = battle_data[i].defval; |
---|
3856 | } |
---|
3857 | |
---|
3858 | *battle_data[i].val = val; |
---|
3859 | return 1; |
---|
3860 | } |
---|
3861 | |
---|
3862 | int battle_get_value(const char* w1) |
---|
3863 | { |
---|
3864 | int i; |
---|
3865 | ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); |
---|
3866 | if (i == ARRAYLENGTH(battle_data)) |
---|
3867 | return 0; // not found |
---|
3868 | else |
---|
3869 | return *battle_data[i].val; |
---|
3870 | } |
---|
3871 | |
---|
3872 | void battle_set_defaults() |
---|
3873 | { |
---|
3874 | int i; |
---|
3875 | for (i = 0; i < ARRAYLENGTH(battle_data); i++) |
---|
3876 | *battle_data[i].val = battle_data[i].defval; |
---|
3877 | } |
---|
3878 | |
---|
3879 | void battle_adjust_conf() |
---|
3880 | { |
---|
3881 | battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10; |
---|
3882 | battle_config.max_aspd = 2000 - battle_config.max_aspd*10; |
---|
3883 | battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed; |
---|
3884 | battle_config.max_cart_weight *= 10; |
---|
3885 | |
---|
3886 | if(battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] |
---|
3887 | battle_config.max_def = 100; |
---|
3888 | |
---|
3889 | if(battle_config.min_hitrate > battle_config.max_hitrate) |
---|
3890 | battle_config.min_hitrate = battle_config.max_hitrate; |
---|
3891 | |
---|
3892 | if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex |
---|
3893 | battle_config.pet_max_atk1 = battle_config.pet_max_atk2; |
---|
3894 | |
---|
3895 | if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor] |
---|
3896 | battle_config.day_duration = 60000; |
---|
3897 | if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor] |
---|
3898 | battle_config.night_duration = 60000; |
---|
3899 | |
---|
3900 | #ifndef CELL_NOSTACK |
---|
3901 | if (battle_config.cell_stack_limit != 1) |
---|
3902 | ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); |
---|
3903 | #endif |
---|
3904 | } |
---|
3905 | |
---|
3906 | int battle_config_read(const char* cfgName) |
---|
3907 | { |
---|
3908 | char line[1024], w1[1024], w2[1024]; |
---|
3909 | FILE* fp; |
---|
3910 | static int count = 0; |
---|
3911 | |
---|
3912 | if (count == 0) |
---|
3913 | battle_set_defaults(); |
---|
3914 | |
---|
3915 | count++; |
---|
3916 | |
---|
3917 | fp = fopen(cfgName,"r"); |
---|
3918 | if (fp == NULL) |
---|
3919 | ShowError("File not found: %s\n", cfgName); |
---|
3920 | else |
---|
3921 | { |
---|
3922 | while(fgets(line, sizeof(line), fp)) |
---|
3923 | { |
---|
3924 | if (line[0] == '/' && line[1] == '/') |
---|
3925 | continue; |
---|
3926 | if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) |
---|
3927 | continue; |
---|
3928 | if (strcmpi(w1, "import") == 0) |
---|
3929 | battle_config_read(w2); |
---|
3930 | else |
---|
3931 | if (battle_set_value(w1, w2) == 0) |
---|
3932 | ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); |
---|
3933 | } |
---|
3934 | |
---|
3935 | fclose(fp); |
---|
3936 | } |
---|
3937 | |
---|
3938 | count--; |
---|
3939 | |
---|
3940 | if (count == 0) |
---|
3941 | battle_adjust_conf(); |
---|
3942 | |
---|
3943 | return 0; |
---|
3944 | } |
---|
3945 | |
---|
3946 | void do_init_battle(void) |
---|
3947 | { |
---|
3948 | delay_damage_ers = ers_new(sizeof(struct delay_damage)); |
---|
3949 | add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); |
---|
3950 | } |
---|
3951 | |
---|
3952 | void do_final_battle(void) |
---|
3953 | { |
---|
3954 | ers_destroy(delay_damage_ers); |
---|
3955 | } |
---|