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