1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "ie_feats.h" //cannot avoid declaring these
22 #include "opcode_params.h"
28 #include "DisplayMessage.h"
29 #include "EffectQueue.h"
32 #include "Interface.h"
33 #include "Projectile.h" //needs for clearair
34 #include "Spell.h" //needed for fx_cast_spell feedback
35 #include "TileMap.h" //needs for knock!
37 #include "GameScript/GSUtils.h" //needs for MoveBetweenAreasCore
38 #include "GUI/GameControl.h"
39 #include "Scriptable/Actor.h"
40 #include "PolymorphCache.h" // fx_polymorph
41 #include "Scriptable/PCStatStruct.h" //fx_polymorph (action definitions)
43 //FIXME: find a way to handle portrait icons better
54 #define PI_HOPELESS 44
55 #define PI_LEVELDRAIN 53
56 #define PI_FEEBLEMIND 54
63 #define PI_BLOODRAGE 76 //iwd2
66 #define PI_STONESKIN 80
67 #define PI_DEAFNESS 83 //iwd2
68 #define PI_SEQUENCER 92
70 #define PI_IMPROVEDHASTE 110
71 #define PI_SPELLTRAP 117
72 #define PI_CSHIELD 162
73 #define PI_CSHIELD2 163
75 static ieResRef
*casting_glows
= NULL
;
76 static int cgcount
= -1;
77 static ieResRef
*spell_hits
= NULL
;
78 static bool enhanced_effects
= false;
79 static int shcount
= -1;
80 static int *spell_abilities
= NULL
;
81 static ieDword splabcount
= 0;
82 static int *polymorph_stats
= NULL
;
83 static int polystatcount
= 0;
84 static bool pstflags
= false;
86 //the original engine stores the colors in sprklclr.2da in a different order
88 static ScriptedAnimation default_spell_hit
;
90 int fx_ac_vs_damage_type_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//00
91 int fx_attacks_per_round_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//01
92 int fx_cure_sleep_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//02
93 int fx_set_berserk_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//03
94 int fx_cure_berserk_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//04
95 int fx_set_charmed_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//05
96 int fx_charisma_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//06
97 int fx_set_color_gradient (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//07
98 int fx_set_color_rgb (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//08
99 int fx_set_color_rgb_global (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//08
100 int fx_set_color_pulse_rgb (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//09
101 int fx_set_color_pulse_rgb_global (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//09
102 int fx_constitution_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0a
103 int fx_cure_poisoned_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0b
104 int fx_damage (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0c
105 int fx_death (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0d
106 int fx_cure_frozen_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0e
107 int fx_dexterity_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0f
108 int fx_set_hasted_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10
109 int fx_current_hp_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11
110 int fx_maximum_hp_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12
111 int fx_intelligence_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//13
112 int fx_set_invisible_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//14
113 int fx_lore_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//15
114 int fx_luck_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//16
115 int fx_morale_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//17
116 int fx_set_panic_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//18
117 int fx_set_poisoned_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//19
118 int fx_remove_curse (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1a
119 int fx_acid_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1b
120 int fx_cold_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1c
121 int fx_electricity_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1d
122 int fx_fire_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1e
123 int fx_magic_damage_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//1f
124 int fx_cure_dead_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//20
125 int fx_save_vs_death_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//21
126 int fx_save_vs_wands_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//22
127 int fx_save_vs_poly_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//23
128 int fx_save_vs_breath_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//24
129 int fx_save_vs_spell_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//25
130 int fx_set_silenced_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//26
131 int fx_set_unconscious_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//27
132 int fx_set_slowed_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//28
133 int fx_sparkle(Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//29
134 int fx_bonus_wizard_spells (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2a
135 int fx_cure_petrified_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2b
136 int fx_strength_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2c
137 int fx_set_stun_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2d
138 int fx_cure_stun_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2e
139 int fx_cure_invisible_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//2f
140 int fx_cure_silenced_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//30
141 int fx_wisdom_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//31
142 int fx_brief_rgb (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//32
143 int fx_darken_rgb (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//33
144 int fx_glow_rgb (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//34
145 int fx_animation_id_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//35
146 int fx_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//36
147 int fx_kill_creature_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//37
148 int fx_alignment_invert (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//38
149 int fx_alignment_change (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//39
150 int fx_dispel_effects (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3a
151 int fx_stealth_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3b
152 int fx_miscast_magic_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3c
153 int fx_alchemy_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3d
154 int fx_bonus_priest_spells (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3e
155 int fx_set_infravision_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//3f
156 int fx_cure_infravision_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//40
157 int fx_set_blur_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//41
158 int fx_transparency_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//42
159 int fx_summon_creature (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//43
160 int fx_unsummon_creature (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//44
161 int fx_set_nondetection_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//45
162 int fx_cure_nondetection_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//46
163 int fx_sex_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//47
164 int fx_ids_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//48
165 int fx_damage_bonus_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//49
166 int fx_set_blind_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//4a
167 int fx_cure_blind_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//4b
168 int fx_set_feebleminded_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//4c
169 int fx_cure_feebleminded_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//4d
170 int fx_set_diseased_state (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//4e
171 int fx_cure_diseased_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//4f
172 int fx_set_deaf_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //50
173 int fx_set_deaf_state_iwd2 (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //50
174 int fx_cure_deaf_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//51
175 int fx_set_ai_script (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//52
176 int fx_protection_from_projectile (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//53
177 int fx_magical_fire_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//54
178 int fx_magical_cold_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//55
179 int fx_slashing_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//56
180 int fx_crushing_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//57
181 int fx_piercing_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//58
182 int fx_missiles_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//59
183 int fx_open_locks_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5a
184 int fx_find_traps_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5b
185 int fx_pick_pockets_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5c
186 int fx_fatigue_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5d
187 int fx_intoxication_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5e
188 int fx_tracking_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//5f
189 int fx_level_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//60
190 int fx_strength_bonus_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//61
191 int fx_set_regenerating_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//62
192 int fx_spell_duration_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);///63
193 int fx_generic_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//64 protection from creature is a generic effect
194 int fx_protection_opcode(Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //65
195 int fx_protection_spelllevel (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //66
196 int fx_change_name (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//67
197 int fx_experience_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//68
198 int fx_gold_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//69
199 int fx_morale_break_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//6a
200 int fx_portrait_change (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//6b
201 int fx_reputation_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//6c
202 int fx_hold_creature_no_icon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//6d
203 //int fx_retreat_from (Scriptable* Owner, Actor* target, Effect* fx);//6e reused
204 int fx_create_magic_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//6f
205 int fx_remove_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//70
206 int fx_equip_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//71
207 int fx_dither (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//72
208 int fx_detect_alignment (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//73
209 //int fx_cure_improved_invisible_state (Scriptable* Owner, Actor* target, Effect* fx);//74 (2f)
210 int fx_reveal_area (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//75
211 int fx_reveal_creatures (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//76
212 int fx_mirror_image (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//77
213 int fx_immune_to_weapon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//78
214 int fx_visual_animation_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//79 unknown
215 int fx_create_inventory_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7a
216 int fx_remove_inventory_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7b
217 int fx_dimension_door (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7c
218 int fx_knock (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7d
219 int fx_movement_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7e
220 int fx_monster_summoning (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//7f
221 int fx_set_confused_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//80
222 int fx_set_aid_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//81
223 int fx_set_bless_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//82
224 int fx_set_chant_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//83
225 int fx_set_holy_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//84
226 int fx_luck_non_cumulative (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//85
227 int fx_luck_cumulative (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//85
228 int fx_set_petrified_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//86
229 int fx_polymorph (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//87
230 int fx_force_visible (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//88
231 int fx_set_chantbad_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//89
232 int fx_animation_stance (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8a
233 int fx_display_string (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8b
234 int fx_casting_glow (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8c
235 int fx_visual_spell_hit (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8d
236 int fx_display_portrait_icon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8e
237 int fx_create_item_in_slot (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//8f
238 int fx_disable_button (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//90
239 int fx_disable_spellcasting (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//91
240 int fx_cast_spell (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//92
241 int fx_learn_spell (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//93
242 int fx_cast_spell_point (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//94
243 int fx_identify (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//95
244 int fx_find_traps (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//96
245 int fx_replace_creature (Scriptable
* Owner
, Actor
* target
, Effect
*fx
);//97
246 int fx_play_movie (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//98
247 int fx_set_sanctuary_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//99
248 int fx_set_entangle_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9a
249 int fx_set_minorglobe_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9b
250 int fx_set_shieldglobe_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9c
251 int fx_set_web_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9d
252 int fx_set_grease_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9e
253 int fx_mirror_image_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//9f
254 int fx_cure_sanctuary_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a0
255 int fx_cure_panic_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a1
256 int fx_cure_hold_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a2 //cures 175
257 int fx_cure_slow_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a3
258 int fx_cure_intoxication (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a4
259 int fx_pause_target (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a5
260 int fx_magic_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a6
261 int fx_missile_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a7
262 int fx_remove_creature (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a8
263 int fx_disable_portrait_icon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//a9
264 int fx_damage_animation (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//aa
265 int fx_add_innate (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ab
266 int fx_remove_spell (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ac
267 int fx_poison_resistance_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ad
268 int fx_playsound (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ae
269 int fx_hold_creature (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//af
270 // this function is exactly the same as 0x7e fx_movement_modifier (in bg2 at least)//b0
271 int fx_apply_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//b1
272 //b2 //hitbonus against creature (generic_effect)
273 //b3 //damagebonus against creature (generic effect)
274 //b4 //restrict item (generic effect)
275 //b5 //restrict itemtype (generic effect)
276 int fx_apply_effect_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//b6
277 int fx_apply_effect_item_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//b7
278 int fx_dontjump_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//b8
279 // this function is exactly the same as 0xaf hold_creature (in bg2 at least) //b9
280 int fx_move_to_area (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ba
281 int fx_local_variable (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//bb
282 int fx_auracleansing_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//bc
283 int fx_castingspeed_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//bd
284 int fx_attackspeed_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//be
285 int fx_castinglevel_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//bf
286 int fx_find_familiar (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c0
287 int fx_see_invisible_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c1
288 int fx_ignore_dialogpause_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c2
289 int fx_familiar_constitution_loss (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c3
290 int fx_familiar_marker (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c4
291 int fx_bounce_projectile (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c5
292 int fx_bounce_opcode (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c6
293 int fx_bounce_spelllevel (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c7
294 int fx_bounce_spelllevel_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c8
295 int fx_protection_spelllevel_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//c9
296 int fx_bounce_school (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ca
297 int fx_bounce_secondary_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//cb
298 int fx_protection_school (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //cc
299 int fx_protection_secondary_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //cd
300 int fx_resist_spell (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ce
301 int fx_resist_spell_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//??
302 int fx_bounce_spell (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//cf
303 int fx_bounce_spell_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//??
304 int fx_minimum_hp_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d0
305 int fx_power_word_kill (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d1
306 int fx_power_word_stun (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d2
307 int fx_imprisonment (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d3
308 int fx_freedom (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d4
309 int fx_maze (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d5
310 int fx_select_spell (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d6
311 int fx_play_visual_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
); //d7
312 int fx_leveldrain_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d8
313 int fx_power_word_sleep (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//d9
314 int fx_stoneskin_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//da
315 //db ac vs creature type (general effect)
316 int fx_dispel_school (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//dc
317 int fx_dispel_secondary_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//dd
318 int fx_teleport_field (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//de
319 int fx_protection_school_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//df
320 int fx_cure_leveldrain (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e0
321 int fx_reveal_magic (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e1
322 int fx_protection_secondary_type_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e2
323 int fx_bounce_school_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e3
324 int fx_bounce_secondary_type_dec (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e4
325 int fx_dispel_school_one (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e5
326 int fx_dispel_secondary_type_one (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e6
327 int fx_timestop (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e7
328 int fx_cast_spell_on_condition (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e8
329 int fx_proficiency (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//e9
330 int fx_create_contingency (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ea
331 int fx_wing_buffet (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//eb
332 int fx_puppet_master (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ec
333 int fx_puppet_marker (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ed
334 int fx_disintegrate (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ee
335 int fx_farsee (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ef
336 int fx_remove_portrait_icon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f0
337 //f1 control creature (see charm)
338 int fx_cure_confused_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f2
339 int fx_drain_items (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f3
340 int fx_drain_spells (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f4
341 int fx_checkforberserk_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f5
342 int fx_berserkstage1_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f6
343 int fx_berserkstage2_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f7
344 int fx_melee_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f8
345 int fx_ranged_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//f9
346 int fx_damageluck_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//fa
347 int fx_change_bardsong (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//fb
348 int fx_set_area_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//fc (set trap)
349 int fx_set_map_note (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//fd
350 int fx_remove_map_note (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//fe
351 int fx_create_item_days (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//ff
352 int fx_store_spell_sequencer (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//0x100
353 int fx_create_spell_sequencer (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//101
354 int fx_activate_spell_sequencer (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//102
355 int fx_spelltrap (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//103
356 int fx_crash (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//104, disabled
357 int fx_restore_spell_level (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//105
358 int fx_visual_range_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//106
359 int fx_backstab_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//107
360 int fx_drop_weapon (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//108
361 int fx_modify_global_variable (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//109
362 int fx_remove_immunity (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10a
363 int fx_protection_from_string (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10b
364 int fx_explore_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10c
365 int fx_screenshake (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10d
366 int fx_unpause_caster (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10e
367 int fx_avatar_removal (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//10f
368 int fx_apply_effect_repeat (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//110
369 int fx_remove_projectile (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//111
370 int fx_teleport_to_target (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//112
371 int fx_hide_in_shadows_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//113
372 int fx_detect_illusion_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//114
373 int fx_set_traps_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//115
374 int fx_to_hit_bonus_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//116
375 int fx_renable_button (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//117
376 int fx_force_surge_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//118
377 int fx_wild_surge_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//119
378 int fx_scripting_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11a
379 int fx_apply_effect_curse (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11b
380 int fx_melee_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11c
381 int fx_melee_damage_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11d
382 int fx_missile_damage_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11e
383 int fx_no_circle_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//11f
384 int fx_fist_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//120
385 int fx_fist_damage_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//121
386 int fx_title_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//122
387 int fx_disable_overlay_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//123
388 int fx_no_backstab_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//124
389 int fx_offscreenai_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//125
390 int fx_existance_delay_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//126
391 int fx_disable_chunk_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//127
392 int fx_protection_from_animation (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//128
393 int fx_protection_from_turn (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//129
394 int fx_cutscene2 (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12a
395 int fx_chaos_shield_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12b
396 int fx_npc_bump (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12c
397 int fx_critical_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12d
398 int fx_can_use_any_item_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12e
399 int fx_always_backstab_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//12f
400 int fx_mass_raise_dead (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//130
401 int fx_left_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//131
402 int fx_right_to_hit_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//132
403 int fx_reveal_tracks (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//133
404 int fx_protection_from_tracking (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//134
405 int fx_modify_local_variable (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//135
406 int fx_timeless_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//136
407 int fx_generate_wish (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//137
409 //139 HLA generic effect
410 int fx_golem_stoneskin_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//13a
411 int fx_avatar_removal_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//13b
412 int fx_magical_rest (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//13c
413 //int fx_improved_haste_state (Scriptable* Owner, Actor* target, Effect* fx);//13d same as haste
415 int fx_unknown (Scriptable
* Owner
, Actor
* target
, Effect
* fx
);//???
417 // FIXME: Make this an ordered list, so we could use bsearch!
418 static EffectRef effectnames
[] = {
419 { "*Crash*", fx_crash
, -1 },
420 { "AcidResistanceModifier", fx_acid_resistance_modifier
, -1 },
421 { "ACVsCreatureType", fx_generic_effect
, -1 }, //0xdb
422 { "ACVsDamageTypeModifier", fx_ac_vs_damage_type_modifier
, -1 },
423 { "ACVsDamageTypeModifier2", fx_ac_vs_damage_type_modifier
, -1 }, // used in IWD
424 { "AidNonCumulative", fx_set_aid_state
, -1 },
425 { "AIIdentifierModifier", fx_ids_modifier
, -1 },
426 { "AlchemyModifier", fx_alchemy_modifier
, -1 },
427 { "Alignment:Change", fx_alignment_change
, -1 },
428 { "Alignment:Invert", fx_alignment_invert
, -1 },
429 { "AlwaysBackstab", fx_always_backstab_modifier
, -1 },
430 { "AnimationIDModifier", fx_animation_id_modifier
, -1 },
431 { "AnimationStateChange", fx_animation_stance
, -1 },
432 { "ApplyEffect", fx_apply_effect
, -1 },
433 { "ApplyEffectCurse", fx_apply_effect_curse
, -1 },
434 { "ApplyEffectItem", fx_apply_effect_item
, -1 },
435 { "ApplyEffectItemType", fx_apply_effect_item_type
, -1 },
436 { "ApplyEffectRepeat", fx_apply_effect_repeat
, -1 },
437 { "CutScene2", fx_cutscene2
, -1 },
438 { "AttackSpeedModifier", fx_attackspeed_modifier
, -1 },
439 { "AttacksPerRoundModifier", fx_attacks_per_round_modifier
, -1 },
440 { "AuraCleansingModifier", fx_auracleansing_modifier
, -1 },
441 { "AvatarRemoval", fx_avatar_removal
, -1 }, //unknown
442 { "AvatarRemovalModifier", fx_avatar_removal_modifier
, -1 },
443 { "BackstabModifier", fx_backstab_modifier
, -1 },
444 { "BerserkStage1Modifier", fx_berserkstage1_modifier
, -1},
445 { "BerserkStage2Modifier", fx_berserkstage2_modifier
, -1},
446 { "BlessNonCumulative", fx_set_bless_state
, -1 },
447 { "Bounce:School", fx_bounce_school
, -1 },
448 { "Bounce:SchoolDec", fx_bounce_school_dec
, -1 },
449 { "Bounce:SecondaryType", fx_bounce_secondary_type
, -1 },
450 { "Bounce:SecondaryTypeDec", fx_bounce_secondary_type_dec
, -1 },
451 { "Bounce:Spell", fx_bounce_spell
, -1 },
452 { "Bounce:SpellDec", fx_bounce_spell_dec
, -1 },
453 { "Bounce:SpellLevel", fx_bounce_spelllevel
, -1},
454 { "Bounce:SpellLevelDec", fx_bounce_spelllevel_dec
, -1},
455 { "Bounce:Opcode", fx_bounce_opcode
, -1 },
456 { "Bounce:Projectile", fx_bounce_projectile
, -1 },
457 { "CantUseItem", fx_generic_effect
, -1 },
458 { "CantUseItemType", fx_generic_effect
, -1 },
459 { "CanUseAnyItem", fx_can_use_any_item_modifier
, -1 },
460 { "CastFromList", fx_select_spell
, -1 },
461 { "CastingGlow", fx_casting_glow
, -1 },
462 { "CastingGlow2", fx_casting_glow
, -1 }, //used in iwd
463 { "CastingLevelModifier", fx_castinglevel_modifier
, -1 },
464 { "CastingSpeedModifier", fx_castingspeed_modifier
, -1 },
465 { "CastSpellOnCondition", fx_cast_spell_on_condition
, -1 },
466 { "ChangeBardSong", fx_change_bardsong
, -1 },
467 { "ChangeName", fx_change_name
, -1 },
468 { "ChantBadNonCumulative", fx_set_chantbad_state
, -1 },
469 { "ChantNonCumulative", fx_set_chant_state
, -1 },
470 { "ChaosShieldModifier", fx_chaos_shield_modifier
, -1 },
471 { "CharismaModifier", fx_charisma_modifier
, -1 },
472 { "CheckForBerserkModifier", fx_checkforberserk_modifier
, -1},
473 { "ColdResistanceModifier", fx_cold_resistance_modifier
, -1 },
474 { "Color:BriefRGB", fx_brief_rgb
, -1},
475 { "Color:GlowRGB", fx_glow_rgb
, -1},
476 { "Color:DarkenRGB", fx_darken_rgb
, -1},
477 { "Color:SetPalette", fx_set_color_gradient
, -1 },
478 { "Color:SetRGB", fx_set_color_rgb
, -1 },
479 { "Color:SetRGBGlobal", fx_set_color_rgb_global
, -1 }, //08
480 { "Color:PulseRGB", fx_set_color_pulse_rgb
, -1 }, //9
481 { "Color:PulseRGBGlobal", fx_set_color_pulse_rgb_global
, -1 }, //9
482 { "ConstitutionModifier", fx_constitution_modifier
, -1 },
483 { "ControlCreature", fx_set_charmed_state
, -1 }, //0xf1 same as charm
484 { "CreateContingency", fx_create_contingency
, -1 },
485 { "CriticalHitModifier", fx_critical_hit_modifier
, -1 },
486 { "CrushingResistanceModifier", fx_crushing_resistance_modifier
, -1 },
487 { "Cure:Berserk", fx_cure_berserk_state
, -1 },
488 { "Cure:Blind", fx_cure_blind_state
, -1 },
489 { "Cure:CasterHold", fx_unpause_caster
, -1 },
490 { "Cure:Confusion", fx_cure_confused_state
, -1 },
491 { "Cure:Deafness", fx_cure_deaf_state
, -1 },
492 { "Cure:Death", fx_cure_dead_state
, -1 },
493 { "Cure:Defrost", fx_cure_frozen_state
, -1 },
494 { "Cure:Disease", fx_cure_diseased_state
, -1 },
495 { "Cure:Feeblemind", fx_cure_feebleminded_state
, -1 },
496 { "Cure:Hold", fx_cure_hold_state
, -1 },
497 { "Cure:Imprisonment", fx_freedom
, -1 },
498 { "Cure:Infravision", fx_cure_infravision_state
, -1 },
499 { "Cure:Intoxication", fx_cure_intoxication
, -1 }, //0xa4 (iwd2 has this working)
500 { "Cure:Invisible", fx_cure_invisible_state
, -1 }, //0x2f
501 { "Cure:Invisible2", fx_cure_invisible_state
, -1 }, //0x74
502 //{ "Cure:ImprovedInvisible", fx_cure_improved_invisible_state, -1 },
503 { "Cure:LevelDrain", fx_cure_leveldrain
, -1}, //restoration
504 { "Cure:Nondetection", fx_cure_nondetection_state
, -1 },
505 { "Cure:Panic", fx_cure_panic_state
, -1 },
506 { "Cure:Petrification", fx_cure_petrified_state
, -1 },
507 { "Cure:Poison", fx_cure_poisoned_state
, -1 },
508 { "Cure:Sanctuary", fx_cure_sanctuary_state
, -1 },
509 { "Cure:Silence", fx_cure_silenced_state
, -1 },
510 { "Cure:Sleep", fx_cure_sleep_state
, -1 },
511 { "Cure:Stun", fx_cure_stun_state
, -1 },
512 { "CurrentHPModifier", fx_current_hp_modifier
, -1 },
513 { "Damage", fx_damage
, -1 },
514 { "DamageAnimation", fx_damage_animation
, -1 },
515 { "DamageBonusModifier", fx_damage_bonus_modifier
, -1 },
516 { "DamageLuckModifier", fx_damageluck_modifier
, -1 },
517 { "DamageVsCreature", fx_generic_effect
, -1 },
518 { "Death", fx_death
, -1 },
519 { "Death2", fx_death
, -1 }, //(iwd2 effect)
520 { "Death3", fx_death
, -1 }, //(iwd2 effect too, Banish)
521 { "DetectAlignment", fx_detect_alignment
, -1 },
522 { "DetectIllusionsModifier", fx_detect_illusion_modifier
, -1 },
523 { "DexterityModifier", fx_dexterity_modifier
, -1 },
524 { "DimensionDoor", fx_dimension_door
, -1 },
525 { "DisableButton", fx_disable_button
, -1 }, //sets disable button flag
526 { "DisableChunk", fx_disable_chunk_modifier
, -1 },
527 { "DisableOverlay", fx_disable_overlay_modifier
, -1 },
528 { "DisableCasting", fx_disable_spellcasting
, -1 },
529 { "Disintegrate", fx_disintegrate
, -1 },
530 { "DispelEffects", fx_dispel_effects
, -1 },
531 { "DispelSchool", fx_dispel_school
, -1 },
532 { "DispelSchoolOne", fx_dispel_school_one
, -1 },
533 { "DispelSecondaryType", fx_dispel_secondary_type
, -1 },
534 { "DispelSecondaryTypeOne", fx_dispel_secondary_type_one
, -1 },
535 { "DisplayString", fx_display_string
, -1 },
536 { "Dither", fx_dither
, -1 },
537 { "DontJumpModifier", fx_dontjump_modifier
, -1 },
538 { "DrainItems", fx_drain_items
, -1 },
539 { "DrainSpells", fx_drain_spells
, -1 },
540 { "DropWeapon", fx_drop_weapon
, -1 },
541 { "ElectricityResistanceModifier", fx_electricity_resistance_modifier
, -1 },
542 { "ExistanceDelayModifier", fx_existance_delay_modifier
, -1 }, //unknown
543 { "ExperienceModifier", fx_experience_modifier
, -1 },
544 { "ExploreModifier", fx_explore_modifier
, -1 },
545 { "FamiliarBond", fx_familiar_constitution_loss
, -1 },
546 { "FamiliarMarker", fx_familiar_marker
, -1},
547 { "Farsee", fx_farsee
, -1},
548 { "FatigueModifier", fx_fatigue_modifier
, -1 },
549 { "FindFamiliar", fx_find_familiar
, -1 },
550 { "FindTraps", fx_find_traps
, -1 },
551 { "FindTrapsModifier", fx_find_traps_modifier
, -1 },
552 { "FireResistanceModifier", fx_fire_resistance_modifier
, -1 },
553 { "FistDamageModifier", fx_fist_damage_modifier
, -1 },
554 { "FistHitModifier", fx_fist_to_hit_modifier
, -1 },
555 { "ForceSurgeModifier", fx_force_surge_modifier
, -1 },
556 { "ForceVisible", fx_force_visible
, -1 }, //not invisible but improved invisible
557 { "FreeAction", fx_cure_slow_state
, -1},
558 { "GenerateWish", fx_generate_wish
, -1},
559 { "GoldModifier", fx_gold_modifier
, -1 },
560 { "HideInShadowsModifier", fx_hide_in_shadows_modifier
, -1},
561 { "HLA", fx_generic_effect
, -1},
562 { "HolyNonCumulative", fx_set_holy_state
, -1 },
563 { "Icon:Disable", fx_disable_portrait_icon
, -1 },
564 { "Icon:Display", fx_display_portrait_icon
, -1 },
565 { "Icon:Remove", fx_remove_portrait_icon
, -1 },
566 { "Identify", fx_identify
, -1 },
567 { "IgnoreDialogPause", fx_ignore_dialogpause_modifier
, -1 },
568 { "IntelligenceModifier", fx_intelligence_modifier
, -1 },
569 { "IntoxicationModifier", fx_intoxication_modifier
, -1 },
570 { "InvisibleDetection", fx_see_invisible_modifier
, -1 },
571 { "Item:CreateDays", fx_create_item_days
, -1 },
572 { "Item:CreateInSlot", fx_create_item_in_slot
, -1 },
573 { "Item:CreateInventory", fx_create_inventory_item
, -1 },
574 { "Item:CreateMagic", fx_create_magic_item
, -1 },
575 { "Item:Equip", fx_equip_item
, -1 }, //71
576 { "Item:Remove", fx_remove_item
, -1 }, //70
577 { "Item:RemoveInventory", fx_remove_inventory_item
, -1 },
578 { "KillCreatureType", fx_kill_creature_type
, -1 },
579 { "LevelModifier", fx_level_modifier
, -1 },
580 { "LevelDrainModifier", fx_leveldrain_modifier
, -1 },
581 { "LoreModifier", fx_lore_modifier
, -1 },
582 { "LuckModifier", fx_luck_modifier
, -1 },
583 { "LuckCumulative", fx_luck_cumulative
, -1 },
584 { "LuckNonCumulative", fx_luck_non_cumulative
, -1 },
585 { "MagicalColdResistanceModifier", fx_magical_cold_resistance_modifier
, -1 },
586 { "MagicalFireResistanceModifier", fx_magical_fire_resistance_modifier
, -1 },
587 { "MagicalRest", fx_magical_rest
, -1 },
588 { "MagicDamageResistanceModifier", fx_magic_damage_resistance_modifier
, -1 },
589 { "MagicResistanceModifier", fx_magic_resistance_modifier
, -1 },
590 { "MassRaiseDead", fx_mass_raise_dead
, -1 },
591 { "MaximumHPModifier", fx_maximum_hp_modifier
, -1 },
592 { "Maze", fx_maze
, -1},
593 { "MeleeDamageModifier", fx_melee_damage_modifier
, -1 },
594 { "MeleeHitModifier", fx_melee_to_hit_modifier
, -1 },
595 { "MinimumHPModifier", fx_minimum_hp_modifier
, -1 },
596 { "MiscastMagicModifier", fx_miscast_magic_modifier
, -1 },
597 { "MissileDamageModifier", fx_missile_damage_modifier
, -1 },
598 { "MissileHitModifier", fx_missile_to_hit_modifier
, -1 },
599 { "MissilesResistanceModifier", fx_missiles_resistance_modifier
, -1 },
600 { "MirrorImage", fx_mirror_image
, -1 },
601 { "MirrorImageModifier", fx_mirror_image_modifier
, -1 },
602 { "ModifyGlobalVariable", fx_modify_global_variable
, -1 },
603 { "ModifyLocalVariable", fx_modify_local_variable
, -1 },
604 { "MonsterSummoning", fx_monster_summoning
, -1 },
605 { "MoraleBreakModifier", fx_morale_break_modifier
, -1 },
606 { "MoraleModifier", fx_morale_modifier
, -1 },
607 { "MovementRateModifier", fx_movement_modifier
, -1 }, //fast (7e)
608 { "MovementRateModifier2", fx_movement_modifier
, -1 },//slow (b0)
609 { "MovementRateModifier3", fx_movement_modifier
, -1 },//forced (IWD - 10a)
610 { "MovementRateModifier4", fx_movement_modifier
, -1 },//slow (IWD2 - 1b9)
611 { "MoveToArea", fx_move_to_area
, -1 }, //0xba
612 { "NoCircleState", fx_no_circle_state
, -1 },
613 { "NPCBump", fx_npc_bump
, -1 },
614 { "OffscreenAIModifier", fx_offscreenai_modifier
, -1 },
615 { "OffhandHitModifier", fx_left_to_hit_modifier
, -1 },
616 { "OpenLocksModifier", fx_open_locks_modifier
, -1 },
617 { "Overlay:Entangle", fx_set_entangle_state
, -1 },
618 { "Overlay:Grease", fx_set_grease_state
, -1 },
619 { "Overlay:MinorGlobe", fx_set_minorglobe_state
, -1 },
620 { "Overlay:Sanctuary", fx_set_sanctuary_state
, -1 },
621 { "Overlay:ShieldGlobe", fx_set_shieldglobe_state
, -1 },
622 { "Overlay:Web", fx_set_web_state
, -1 },
623 { "PauseTarget", fx_pause_target
, -1 }, //also known as casterhold
624 { "PickPocketsModifier", fx_pick_pockets_modifier
, -1 },
625 { "PiercingResistanceModifier", fx_piercing_resistance_modifier
, -1 },
626 { "PlayMovie", fx_play_movie
, -1 },
627 { "PlaySound", fx_playsound
, -1 },
628 { "PlayVisualEffect", fx_play_visual_effect
, -1 },
629 { "PoisonResistanceModifier", fx_poison_resistance_modifier
, -1 },
630 { "Polymorph", fx_polymorph
, -1},
631 { "PortraitChange", fx_portrait_change
, -1 },
632 { "PowerWordKill", fx_power_word_kill
, -1 },
633 { "PowerWordSleep", fx_power_word_sleep
, -1 },
634 { "PowerWordStun", fx_power_word_stun
, -1 },
635 { "PriestSpellSlotsModifier", fx_bonus_priest_spells
, -1 },
636 { "Proficiency", fx_proficiency
, -1 },
637 // { "Protection:Animation", fx_protection_from_animation, -1 },
638 { "Protection:Animation", fx_generic_effect
, -1 },
639 { "Protection:Backstab", fx_no_backstab_modifier
, -1 },
640 { "Protection:Creature", fx_generic_effect
, -1 },
641 { "Protection:Opcode", fx_protection_opcode
, -1 },
642 { "Protection:Opcode2", fx_protection_opcode
, -1 },
643 { "Protection:Projectile",fx_protection_from_projectile
, -1},
644 { "Protection:School",fx_generic_effect
,-1},//overlay?
645 { "Protection:SchoolDec",fx_protection_school_dec
,-1},//overlay?
646 { "Protection:SecondaryType",fx_protection_secondary_type
,-1},//overlay?
647 { "Protection:SecondaryTypeDec",fx_protection_secondary_type_dec
,-1},//overlay?
648 { "Protection:Spell",fx_resist_spell
,-1},//overlay?
649 { "Protection:SpellDec",fx_resist_spell_dec
,-1},//overlay?
650 { "Protection:SpellLevel",fx_protection_spelllevel
,-1},//overlay?
651 { "Protection:SpellLevelDec",fx_protection_spelllevel_dec
,-1},//overlay?
652 { "Protection:String", fx_generic_effect
, -1 },
653 { "Protection:Tracking", fx_protection_from_tracking
, -1 },
654 { "Protection:Turn", fx_protection_from_turn
, -1},
655 { "Protection:Weapons", fx_immune_to_weapon
, -1},
656 { "PuppetMarker", fx_puppet_marker
, -1},
657 { "ProjectImage", fx_puppet_master
, -1},
658 { "Reveal:Area", fx_reveal_area
, -1 },
659 { "Reveal:Creatures", fx_reveal_creatures
, -1 },
660 { "Reveal:Magic", fx_reveal_magic
, -1 },
661 { "Reveal:Tracks", fx_reveal_tracks
, -1 },
662 { "RemoveCurse", fx_remove_curse
, -1 },
663 { "RemoveImmunity", fx_remove_immunity
, -1 },
664 { "RemoveMapNote", fx_remove_map_note
, -1 },
665 { "RemoveProjectile", fx_remove_projectile
, -1 }, //removes effects from actor and area
666 { "RenableButton", fx_renable_button
, -1 }, //removes disable button flag
667 { "RemoveCreature", fx_remove_creature
, -1 },
668 { "ReplaceCreature", fx_replace_creature
, -1 },
669 { "ReputationModifier", fx_reputation_modifier
, -1 },
670 { "RestoreSpells", fx_restore_spell_level
, -1 },
671 { "RightHitModifier", fx_right_to_hit_modifier
, -1 },
672 { "SaveVsBreathModifier", fx_save_vs_breath_modifier
, -1 },
673 { "SaveVsDeathModifier", fx_save_vs_death_modifier
, -1 },
674 { "SaveVsPolyModifier", fx_save_vs_poly_modifier
, -1 },
675 { "SaveVsSpellsModifier", fx_save_vs_spell_modifier
, -1 },
676 { "SaveVsWandsModifier", fx_save_vs_wands_modifier
, -1 },
677 { "ScreenShake", fx_screenshake
, -1 },
678 { "ScriptingState", fx_scripting_state
, -1 },
679 { "Sequencer:Activate", fx_activate_spell_sequencer
, -1 },
680 { "Sequencer:Create", fx_create_spell_sequencer
, -1 },
681 { "Sequencer:Store", fx_store_spell_sequencer
, -1 },
682 { "SetAIScript", fx_set_ai_script
, -1 },
683 { "SetMapNote", fx_set_map_note
, -1 },
684 { "SetMeleeEffect", fx_melee_effect
, -1 },
685 { "SetRangedEffect", fx_ranged_effect
, -1 },
686 { "SetTrap", fx_set_area_effect
, -1 },
687 { "SetTrapsModifier", fx_set_traps_modifier
, -1 },
688 { "SexModifier", fx_sex_modifier
, -1 },
689 { "SlashingResistanceModifier", fx_slashing_resistance_modifier
, -1 },
690 { "SlowPoisonDamageRate", fx_generic_effect
, -1 }, //slow poison effect
691 { "Sparkle", fx_sparkle
, -1 },
692 { "SpellDurationModifier", fx_spell_duration_modifier
, -1 },
693 { "Spell:Add", fx_add_innate
, -1 },
694 { "Spell:Cast", fx_cast_spell
, -1 },
695 { "Spell:CastPoint", fx_cast_spell_point
, -1 },
696 { "Spell:Learn", fx_learn_spell
, -1 },
697 { "Spell:Remove", fx_remove_spell
, -1 },
698 { "Spelltrap",fx_spelltrap
, -1 }, //overlay: spmagglo
699 { "State:Berserk", fx_set_berserk_state
, -1 },
700 { "State:Blind", fx_set_blind_state
, -1 },
701 { "State:Blur", fx_set_blur_state
, -1 },
702 { "State:Charmed", fx_set_charmed_state
, -1 }, //0x05
703 { "State:Confused", fx_set_confused_state
, -1 },
704 { "State:Deafness", fx_set_deaf_state
, -1 },
705 { "State:DeafnessIWD2", fx_set_deaf_state_iwd2
, -1 }, //this is a modified version
706 { "State:Diseased", fx_set_diseased_state
, -1 },
707 { "State:Feeblemind", fx_set_feebleminded_state
, -1 },
708 { "State:Hasted", fx_set_hasted_state
, -1 },
709 { "State:Haste2", fx_set_hasted_state
, -1 },
710 { "State:Hold", fx_hold_creature
, -1 }, //175 (doesn't work in original iwd2)
711 { "State:Hold2", fx_hold_creature
, -1 },//185 (doesn't work in original iwd2)
712 { "State:Hold3", fx_hold_creature
, -1 },//109 iwd2
713 { "State:HoldNoIcon", fx_hold_creature_no_icon
, -1 }, //109
714 { "State:HoldNoIcon2", fx_hold_creature_no_icon
, -1 }, //0xfb (iwd/iwd2)
715 { "State:HoldNoIcon3", fx_hold_creature_no_icon
, -1 }, //0x1a8 (iwd2)
716 { "State:Imprisonment", fx_imprisonment
, -1 },
717 { "State:Infravision", fx_set_infravision_state
, -1 },
718 { "State:Invisible", fx_set_invisible_state
, -1 }, //both invis or improved invis
719 { "State:Nondetection", fx_set_nondetection_state
, -1 },
720 { "State:Panic", fx_set_panic_state
, -1 },
721 { "State:Petrification", fx_set_petrified_state
, -1 },
722 { "State:Poisoned", fx_set_poisoned_state
, -1 },
723 { "State:Regenerating", fx_set_regenerating_state
, -1 },
724 { "State:Silenced", fx_set_silenced_state
, -1 },
725 { "State:Helpless", fx_set_unconscious_state
, -1 },
726 { "State:Sleep", fx_set_unconscious_state
, -1},
727 { "State:Slowed", fx_set_slowed_state
, -1 },
728 { "State:Stun", fx_set_stun_state
, -1 },
729 { "StealthModifier", fx_stealth_modifier
, -1 },
730 { "StoneSkinModifier", fx_stoneskin_modifier
, -1 },
731 { "StoneSkin2Modifier", fx_golem_stoneskin_modifier
, -1 },
732 { "StrengthModifier", fx_strength_modifier
, -1 },
733 { "StrengthBonusModifier", fx_strength_bonus_modifier
, -1 },
734 { "SummonCreature", fx_summon_creature
, -1 },
735 { "RandomTeleport", fx_teleport_field
, -1 },
736 { "TeleportToTarget", fx_teleport_to_target
, -1 },
737 { "TimelessState", fx_timeless_modifier
, -1 },
738 { "Timestop", fx_timestop
, -1},
739 { "TitleModifier", fx_title_modifier
, -1 },
740 { "ToHitModifier", fx_to_hit_modifier
, -1 },
741 { "ToHitBonusModifier", fx_to_hit_bonus_modifier
, -1 },
742 { "ToHitVsCreature", fx_generic_effect
, -1 },
743 { "TrackingModifier", fx_tracking_modifier
, -1 },
744 { "TransparencyModifier", fx_transparency_modifier
, -1 },
745 { "Unknown", fx_unknown
, -1},
746 { "Unlock", fx_knock
, -1 }, //open doors/containers
747 { "UnsummonCreature", fx_unsummon_creature
, -1 },
748 { "Variable:StoreLocalVariable", fx_local_variable
, -1 },
749 { "VisualAnimationEffect", fx_visual_animation_effect
, -1 }, //unknown
750 { "VisualRangeModifier", fx_visual_range_modifier
, -1 },
751 { "VisualSpellHit", fx_visual_spell_hit
, -1 },
752 { "WildSurgeModifier", fx_wild_surge_modifier
, -1 },
753 { "WingBuffet", fx_wing_buffet
, -1 },
754 { "WisdomModifier", fx_wisdom_modifier
, -1 },
755 { "WizardSpellSlotsModifier", fx_bonus_wizard_spells
, -1 },
759 static void Cleanup()
761 core
->FreeResRefTable(casting_glows
, cgcount
);
762 core
->FreeResRefTable(spell_hits
, shcount
);
763 if(spell_abilities
) free(spell_abilities
);
764 spell_abilities
=NULL
;
765 if(polymorph_stats
) free(polymorph_stats
);
766 polymorph_stats
=NULL
;
769 void RegisterCoreOpcodes()
771 core
->RegisterOpcodes( sizeof( effectnames
) / sizeof( EffectRef
) - 1, effectnames
);
772 enhanced_effects
=!!core
->HasFeature(GF_ENHANCED_EFFECTS
);
773 pstflags
=!!core
->HasFeature(GF_PST_STATE_FLAGS
);
774 default_spell_hit
.SequenceFlags
|=IE_VVC_BAM
;
778 static inline void SetGradient(Actor
*target
, ieDword gradient
)
780 gradient
|= (gradient
<<16);
781 gradient
|= (gradient
<<8);
782 for(int i
=0;i
<7;i
++) {
783 STAT_SET(IE_COLORS
+i
, gradient
);
787 static inline void HandleBonus(Actor
*target
, int stat
, int mod
, int mode
)
789 if (mode
==FX_DURATION_INSTANT_PERMANENT
) {
790 if (target
->IsReverseToHit()) {
791 BASE_SUB( stat
, mod
);
793 BASE_ADD( stat
, mod
);
797 if (target
->IsReverseToHit()) {
798 STAT_SUB( stat
, mod
);
800 STAT_ADD( stat
, mod
);
805 #define ENEMY_SEES_ORIGIN 1
806 #define ORIGIN_SEES_ENEMY 2
808 inline Actor
*GetNearestEnemyOf(Map
*map
, Actor
*origin
, int whoseeswho
)
810 //determining the allegiance of the origin
811 int type
= GetGroup(origin
);
813 //neutral has no enemies
818 Targets
*tgts
= new Targets();
820 int i
= map
->GetActorCount(true);
823 ac
=map
->GetActor(i
,true);
824 int distance
= Distance(ac
, origin
);
825 if (whoseeswho
&ENEMY_SEES_ORIGIN
) {
826 if (!CanSee(ac
, origin
, true, GA_NO_DEAD
)) {
830 if (whoseeswho
&ORIGIN_SEES_ENEMY
) {
831 if (!CanSee(ac
, origin
, true, GA_NO_DEAD
)) {
836 if (type
) { //origin is PC
837 if (ac
->GetStat(IE_EA
) >= EA_EVILCUTOFF
) {
838 tgts
->AddTarget(ac
, distance
, GA_NO_DEAD
);
842 if (ac
->GetStat(IE_EA
) <= EA_GOODCUTOFF
) {
843 tgts
->AddTarget(ac
, distance
, GA_NO_DEAD
);
847 ac
= (Actor
*) tgts
->GetTarget(0, ST_ACTOR
);
852 inline Scriptable
*GetCaster(Scriptable
*Owner
, Effect
*fx
) {
853 if (fx
->FirstApply
) {
854 fx
->CasterID
= Owner
? Owner
->GetGlobalID() : 0;
857 return core
->GetGame()->GetActorByGlobalID(fx
->CasterID
);
862 //resurrect code used in many places
863 void Resurrect(Scriptable
*Owner
, Actor
*target
, Effect
*fx
, Point
&p
)
865 Scriptable
*caster
= GetCaster(Owner
, fx
);
867 caster
= Owner
; // IE stores the enemyally in the effect instead
869 Map
*area
= caster
->GetCurrentArea();
871 if (area
&& target
->GetCurrentArea()!=area
) {
872 MoveBetweenAreasCore(target
, area
->GetScriptName(), p
, fx
->Parameter2
, true);
878 // handles the percentage damage spread over time by converting it to absolute damage
879 inline void HandlePercentageDamage(Effect
*fx
, Actor
*target
) {
880 if (fx
->Parameter2
== RPD_PERCENT
&& fx
->FirstApply
) {
881 // distribute the damage to one second intervals
882 int seconds
= (fx
->Duration
- core
->GetGame()->GameTime
) / AI_UPDATE_TIME
;
883 fx
->Parameter1
= target
->GetStat(IE_MAXHITPOINTS
) * fx
->Parameter1
/ 100 / seconds
;
888 // 0x00 ACVsDamageTypeModifier
889 int fx_ac_vs_damage_type_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
891 if (0) printf( "fx_ac_vs_damage_type_modifier (%2d): AC Modif: %d ; Type: %d ; MinLevel: %d ; MaxLevel: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
, (int) fx
->DiceSides
, (int) fx
->DiceThrown
);
892 //check level was pulled outside as a common functionality
896 int type
= fx
->Parameter2
;
898 HandleBonus(target
, IE_ARMORCLASS
, fx
->Parameter1
, fx
->TimingMode
);
902 //convert to signed so -1 doesn't turn to an astronomical number
904 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
905 if ((signed)BASE_GET( IE_ARMORCLASS
) > (signed)fx
->Parameter1
) {
906 BASE_SET( IE_ARMORCLASS
, fx
->Parameter1
);
909 if ((signed)STAT_GET( IE_ARMORCLASS
) > (signed)fx
->Parameter1
) {
910 STAT_SET( IE_ARMORCLASS
, fx
->Parameter1
);
916 //the original engine did work with the combination of these bits
917 //but since it crashed, we are not bound to the same rules
919 HandleBonus(target
, IE_ACCRUSHINGMOD
, fx
->Parameter1
, fx
->TimingMode
);
922 HandleBonus(target
, IE_ACMISSILEMOD
, fx
->Parameter1
, fx
->TimingMode
);
925 HandleBonus(target
, IE_ACPIERCINGMOD
, fx
->Parameter1
, fx
->TimingMode
);
928 HandleBonus(target
, IE_ACSLASHINGMOD
, fx
->Parameter1
, fx
->TimingMode
);
934 // 0x01 AttacksPerRoundModifier
935 int fx_attacks_per_round_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
937 if (0) printf( "fx_attacks_per_round_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
938 int tmp
= (signed) fx
->Parameter1
;
939 if (fx
->Parameter2
!=2) {
941 else if (tmp
<-10) tmp
=-10;
944 else if (tmp
<-10) tmp
+=11;
947 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
948 BASE_MOD_VAR(IE_NUMBEROFATTACKS
, tmp
);
950 STAT_MOD_VAR(IE_NUMBEROFATTACKS
, tmp
);
955 // 0x02 Cure:Sleep (Awaken)
956 // this effect clears the STATE_SLEEP (1) bit, but clearing it alone wouldn't remove the
957 // unconscious effect, which is combined with STATE_HELPLESS (0x20+1)
958 static EffectRef fx_set_sleep_state_ref
={"State:Helpless",NULL
,-1};
959 //this reference is used by many other effects
960 static EffectRef fx_display_portrait_icon_ref
={"Icon:Display",NULL
,-1};
962 int fx_cure_sleep_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
964 if (0) printf( "fx_cure_sleep_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
965 BASE_STATE_CURE( STATE_SLEEP
);
966 target
->fxqueue
.RemoveAllEffects(fx_set_sleep_state_ref
);
967 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_SLEEP
);
968 return FX_NOT_APPLIED
;
971 // 0x03 State:Berserk
972 // this effect sets the STATE_BERSERK bit, but bg2 actually ignores the bit
973 int fx_set_berserk_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
975 if (0) printf( "fx_set_berserk_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
976 // atleast how and bg2 allow this to only work on pcs
977 if (!core
->HasFeature(GF_3ED_RULES
) && !target
->InParty
) {
978 return FX_NOT_APPLIED
;
981 if (fx
->FirstApply
) {
982 target
->inventory
.EquipBestWeapon(EQUIP_MELEE
);
985 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
986 BASE_STATE_SET( STATE_BERSERK
);
988 STATE_SET( STATE_BERSERK
);
991 switch(fx
->Parameter2
) {
992 case 1: //always berserk
993 target
->SetSpellState(SS_BERSERK
);
995 target
->AddPortraitIcon(PI_BERSERK
);
998 target
->SetSpellState(SS_BERSERK
);
999 //immunity to effects:
1009 target
->SetSpellState(SS_BLOODRAGE
);
1010 target
->SetSpellState(SS_NOHPINFO
);
1011 target
->SetColorMod(0xff, RGBModifier::ADD
, 15, 128, 0, 0);
1012 target
->AddPortraitIcon(PI_BLOODRAGE
);
1015 return FX_PERMANENT
;
1018 // 0x04 Cure:Berserk
1019 // this effect clears the STATE_BERSERK (2) bit, but bg2 actually ignores the bit
1020 // it also removes effect 04
1021 static EffectRef fx_set_berserk_state_ref
={"State:Berserk",NULL
,-1};
1023 int fx_cure_berserk_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1025 if (0) printf( "fx_cure_berserk_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1026 BASE_STATE_CURE( STATE_BERSERK
);
1027 target
->fxqueue
.RemoveAllEffects(fx_set_berserk_state_ref
);
1028 return FX_NOT_APPLIED
;
1031 // 0x05 State:Charmed
1032 // 0xf1 ControlCreature (iwd2)
1033 int fx_set_charmed_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1035 if (0) printf( "fx_set_charmed_state (%2d): General: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1037 //blood rage berserking gives immunity to charm (in iwd2)
1038 if (target
->HasSpellState(SS_BLOODRAGE
)) {
1039 return FX_NOT_APPLIED
;
1042 //protection from evil gives immunity to charm (in iwd2)
1043 if (target
->HasSpellState(SS_PROTFROMEVIL
)) {
1044 return FX_NOT_APPLIED
;
1047 if (fx
->Parameter1
&& (STAT_GET(IE_GENERAL
)!=fx
->Parameter1
)) {
1048 return FX_NOT_APPLIED
;
1051 Scriptable
*caster
= GetCaster(Owner
, fx
);
1052 if (!caster
) caster
= Owner
; // IE stores the enemyally in the effect instead
1053 bool enemyally
= true;
1054 if (caster
->Type
==ST_ACTOR
) {
1055 enemyally
= ((Actor
*) caster
)->GetStat(IE_EA
)>EA_GOODCUTOFF
; //or evilcutoff?
1058 switch (fx
->Parameter2
) {
1059 case 0: //charmed (target neutral after charm)
1060 if (fx
->FirstApply
) {
1061 displaymsg
->DisplayConstantStringName(STR_CHARMED
, 0xf0f0f0, target
);
1065 case 1: //charmed (target hostile after charm)
1066 if (fx
->FirstApply
) {
1067 displaymsg
->DisplayConstantStringName(STR_CHARMED
, 0xf0f0f0, target
);
1070 if (!target
->InParty
) {
1071 target
->SetBaseNoPCF(IE_EA
, EA_ENEMY
);
1074 case 2: //dire charmed (target neutral after charm)
1075 if (fx
->FirstApply
) {
1076 displaymsg
->DisplayConstantStringName(STR_DIRECHARMED
, 0xf0f0f0, target
);
1080 case 3: //dire charmed (target hostile after charm)
1081 if (fx
->FirstApply
) {
1082 displaymsg
->DisplayConstantStringName(STR_DIRECHARMED
, 0xf0f0f0, target
);
1085 if (!target
->InParty
) {
1086 target
->SetBaseNoPCF(IE_EA
, EA_ENEMY
);
1089 case 4: //controlled by cleric
1090 if (fx
->FirstApply
) {
1091 displaymsg
->DisplayConstantStringName(STR_CONTROLLED
, 0xf0f0f0, target
);
1094 if (!target
->InParty
) {
1095 target
->SetBaseNoPCF(IE_EA
, EA_ENEMY
);
1098 case 5: //thrall (typo comes from original engine doc)
1099 if (fx
->FirstApply
) {
1100 displaymsg
->DisplayConstantStringName(STR_CHARMED
, 0xf0f0f0, target
);
1103 STAT_SET(IE_EA
, EA_ENEMY
);
1104 STAT_SET(IE_THRULLCHARM
, 1);
1105 return FX_PERMANENT
;
1108 STATE_SET( STATE_CHARMED
);
1109 STAT_SET_PCF( IE_EA
, enemyally
?EA_ENEMY
:EA_CHARMED
);
1110 //don't stick if permanent
1111 return FX_PERMANENT
;
1114 // 0x06 CharismaModifier
1115 int fx_charisma_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1117 if (0) printf( "fx_charisma_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1119 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1124 return FX_PERMANENT
;
1127 // 0x07 Color:SetPalette
1128 // this effect might not work in pst, they don't have separate weapon slots
1129 int fx_set_color_gradient (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1131 if (0) printf( "fx_set_color_gradient (%2d): Gradient: %d, Location: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1132 EffectQueue::HackColorEffects(target
, fx
);
1133 target
->SetColor( fx
->Parameter2
, fx
->Parameter1
);
1138 int fx_set_color_rgb (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1140 if (0) printf( "fx_set_color_rgb (%2d): RGB: %x, Location: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1141 EffectQueue::HackColorEffects(target
, fx
);
1142 ieDword location
= fx
->Parameter2
& 0xff;
1143 target
->SetColorMod(location
, RGBModifier::ADD
, -1, fx
->Parameter1
>> 8,
1144 fx
->Parameter1
>> 16, fx
->Parameter1
>> 24);
1148 // 08 Color:SetRGBGlobal
1149 int fx_set_color_rgb_global (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1151 if (0) printf( "fx_set_color_rgb_global (%2d): RGB: %x, Location: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1153 target
->SetColorMod(0xff, RGBModifier::ADD
, -1, fx
->Parameter1
>> 8,
1154 fx
->Parameter1
>> 16, fx
->Parameter1
>> 24);
1159 // 09 Color:PulseRGB
1160 int fx_set_color_pulse_rgb (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1162 if (0) printf( "fx_set_color_pulse_rgb (%2d): RGB: %x, Location: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1163 EffectQueue::HackColorEffects(target
, fx
);
1164 ieDword location
= fx
->Parameter2
& 0xff;
1165 int speed
= (fx
->Parameter2
>> 16) & 0xFF;
1166 target
->SetColorMod(location
, RGBModifier::ADD
, speed
,
1167 fx
->Parameter1
>> 8, fx
->Parameter1
>> 16,
1168 fx
->Parameter1
>> 24);
1173 // 09 Color:PulseRGBGlobal (pst variant)
1174 int fx_set_color_pulse_rgb_global (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1176 if (0) printf( "fx_set_color_pulse_rgb_global (%2d): RGB: %x, Location: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1178 int speed
= (fx
->Parameter2
>> 16) & 0xFF;
1179 target
->SetColorMod(0xff, RGBModifier::ADD
, speed
,
1180 fx
->Parameter1
>> 8, fx
->Parameter1
>> 16,
1181 fx
->Parameter1
>> 24);
1186 // 0x0A ConstitutionModifier
1187 int fx_constitution_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1189 if (0) printf( "fx_constitution_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1191 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1196 return FX_PERMANENT
;
1200 static EffectRef fx_poisoned_state_ref
={"State:Poisoned",NULL
,-1};
1202 int fx_cure_poisoned_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1204 if (0) printf( "fx_cure_poisoned_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1205 //all three steps are present in bg2 and iwd2
1206 BASE_STATE_CURE( STATE_POISONED
);
1207 target
->fxqueue
.RemoveAllEffects( fx_poisoned_state_ref
);
1208 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_POISONED
);
1209 return FX_NOT_APPLIED
;
1213 // this is a very important effect
1214 int fx_damage (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1216 if (0) printf( "fx_damage (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1217 //save for half damage type
1218 ieDword damagetype
= fx
->Parameter2
>>16;
1219 ieDword modtype
= fx
->Parameter2
&3;
1223 Scriptable
*caster
= GetCaster(Owner
, fx
);
1225 target
->Damage(fx
->Parameter1
, damagetype
, caster
, modtype
);
1226 //this effect doesn't stick
1227 return FX_NOT_APPLIED
;
1231 int fx_death (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1233 if (0) printf( "fx_death (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1234 ieDword damagetype
= 0;
1235 switch (fx
->Parameter2
) {
1237 BASE_STATE_SET(STATE_D4
); //not sure, should be charred
1238 damagetype
= DAMAGE_FIRE
;
1241 damagetype
= DAMAGE_CRUSHING
;
1244 damagetype
= DAMAGE_CRUSHING
;
1247 damagetype
= DAMAGE_CRUSHING
|DAMAGE_CHUNKING
;
1250 BASE_STATE_SET(STATE_PETRIFIED
);
1251 damagetype
= DAMAGE_CRUSHING
;
1254 BASE_STATE_SET(STATE_FROZEN
);
1255 damagetype
= DAMAGE_COLD
;
1258 BASE_STATE_SET(STATE_PETRIFIED
);
1259 damagetype
= DAMAGE_CRUSHING
|DAMAGE_CHUNKING
;
1262 BASE_STATE_SET(STATE_FROZEN
);
1263 damagetype
= DAMAGE_COLD
|DAMAGE_CHUNKING
;
1266 damagetype
= DAMAGE_ELECTRICITY
;
1271 damagetype
= DAMAGE_ACID
;
1273 target
->Damage(0, damagetype
, Owner
);
1274 //death has damage type too
1276 //this effect doesn't stick
1277 return FX_NOT_APPLIED
;
1281 int fx_cure_frozen_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1283 if (0) printf( "fx_cure_frozen_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1284 BASE_STATE_CURE( STATE_FROZEN
);
1285 return FX_NOT_APPLIED
;
1288 // 0x0F DexterityModifier
1293 int SpellAbilityDieRoll(Actor
*target
, int which
)
1295 if (which
>=CSA_CNT
) return 6;
1297 ieDword cls
= STAT_GET(IE_CLASS
);
1298 if (!spell_abilities
) {
1299 AutoTable
tab("clssplab");
1301 spell_abilities
= (int *) malloc(sizeof(int)*CSA_CNT
);
1302 for (int ab
=0;ab
<CSA_CNT
;ab
++) {
1303 spell_abilities
[ab
*splabcount
]=6;
1308 splabcount
= tab
->GetRowCount();
1309 spell_abilities
=(int *) malloc(sizeof(int)*splabcount
*CSA_CNT
);
1310 for (int ab
=0;ab
<CSA_CNT
;ab
++) {
1311 for (ieDword i
=0;i
<splabcount
;i
++) {
1312 spell_abilities
[ab
*splabcount
+i
]=atoi(tab
->QueryField(i
,ab
));
1316 if (cls
>=splabcount
) cls
=0;
1317 return spell_abilities
[which
*splabcount
+cls
];
1320 int fx_dexterity_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1322 if (0) printf( "fx_dexterity_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1324 ////how cat's grace: value is based on class
1325 if (fx
->Parameter2
==3) {
1326 fx
->Parameter1
= core
->Roll(1,SpellAbilityDieRoll(target
,0),0);
1330 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1335 return FX_PERMANENT
;
1338 static EffectRef fx_set_slow_state_ref
={"State:Slowed",NULL
,-1};
1339 // 0x10 State:Hasted
1340 // this function removes slowed state, or sets hasted state
1341 int fx_set_hasted_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1343 if (0) printf( "fx_set_hasted_state (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
1344 target
->fxqueue
.RemoveAllEffects(fx_set_slow_state_ref
);
1345 target
->fxqueue
.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref
, PI_SLOWED
);
1346 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1347 BASE_STATE_CURE( STATE_SLOWED
);
1348 BASE_STATE_SET( STATE_HASTED
);
1350 STATE_CURE( STATE_SLOWED
);
1351 STATE_SET( STATE_HASTED
);
1353 target
->NewStat(IE_MOVEMENTRATE
, 200, MOD_PERCENT
);
1354 switch (fx
->Parameter2
) {
1355 case 0: //normal haste
1356 target
->AddPortraitIcon(PI_HASTED
);
1357 STAT_SET(IE_IMPROVEDHASTE
,0);
1358 STAT_SET(IE_ATTACKNUMBERDOUBLE
,0);
1359 STAT_ADD(IE_NUMBEROFATTACKS
, 2);
1360 // -2 initiative bonus
1361 STAT_ADD(IE_PHYSICALSPEED
, 2);
1363 case 1://improved haste
1364 target
->AddPortraitIcon(PI_IMPROVEDHASTE
);
1365 STAT_SET(IE_IMPROVEDHASTE
,1);
1366 STAT_SET(IE_ATTACKNUMBERDOUBLE
,0);
1367 target
->NewStat(IE_NUMBEROFATTACKS
, 200, MOD_PERCENT
);
1368 // -2 initiative bonus
1369 STAT_ADD(IE_PHYSICALSPEED
, 2);
1371 case 2://speed haste only
1372 target
->AddPortraitIcon(PI_HASTED
);
1373 STAT_SET(IE_IMPROVEDHASTE
,0);
1374 STAT_SET(IE_ATTACKNUMBERDOUBLE
,1);
1378 return FX_PERMANENT
;
1381 // 0x11 CurrentHPModifier
1382 int fx_current_hp_modifier (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1384 if (0) printf( "fx_current_hp_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1386 if (fx
->Parameter2
&0x10000) {
1387 Point
p(fx
->PosX
, fx
->PosY
);
1388 Resurrect(Owner
, target
, fx
, p
);
1390 if (fx
->Parameter2
&0x20000) {
1391 target
->fxqueue
.RemoveAllNonPermanentEffects();
1393 //Cannot heal bloodrage
1394 if (target
->HasSpellState(SS_BLOODRAGE
)) {
1395 return FX_NOT_APPLIED
;
1398 //current hp percent is relative to modified max hp
1399 switch(fx
->Parameter2
&0xffff) {
1402 target
->NewBase( IE_HITPOINTS
, fx
->Parameter1
, fx
->Parameter2
&0xffff);
1405 target
->NewBase( IE_HITPOINTS
, target
->GetSafeStat(IE_MAXHITPOINTS
)*fx
->Parameter1
/100, MOD_ABSOLUTE
);
1407 //never stay permanent
1408 return FX_NOT_APPLIED
;
1411 // 0x12 MaximumHPModifier
1412 // 0 and 3 differ in that 3 doesn't modify current hitpoints
1413 // 1,4 and 2,5 are analogous to them, but with different modifiers
1414 int fx_maximum_hp_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1416 if (0) printf( "fx_maximum_hp_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1418 if (STATE_GET( STATE_DEAD
|STATE_PETRIFIED
|STATE_FROZEN
) ) {
1419 return FX_NOT_APPLIED
;
1422 bool base
= fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
;
1424 switch (fx
->Parameter2
) {
1426 // random value Parameter1 is set by level_check in EffectQueue
1428 BASE_ADD( IE_MAXHITPOINTS
, fx
->Parameter1
);
1429 BASE_ADD( IE_HITPOINTS
, fx
->Parameter1
);
1431 STAT_ADD( IE_MAXHITPOINTS
, fx
->Parameter1
);
1432 if (fx
->FirstApply
) {
1433 BASE_ADD( IE_HITPOINTS
, fx
->Parameter1
);
1437 case 3: // no current hp bonus
1438 // random value Parameter1 is set by level_check in EffectQueue
1440 BASE_ADD( IE_MAXHITPOINTS
, fx
->Parameter1
);
1442 STAT_ADD( IE_MAXHITPOINTS
, fx
->Parameter1
);
1445 case 1: // with current hp bonus, but unimplemented in the original
1448 BASE_SET( IE_MAXHITPOINTS
, fx
->Parameter1
);
1450 STAT_SET( IE_MAXHITPOINTS
, fx
->Parameter1
);
1455 BASE_MUL(IE_MAXHITPOINTS
, fx
->Parameter1
);
1456 BASE_MUL(IE_HITPOINTS
, fx
->Parameter1
);
1458 target
->NewStat( IE_MAXHITPOINTS
, target
->GetStat(IE_MAXHITPOINTS
)*fx
->Parameter1
/100, MOD_ABSOLUTE
);
1459 if (fx
->FirstApply
) {
1460 target
->NewBase( IE_HITPOINTS
, target
->GetSafeStat(IE_HITPOINTS
)*fx
->Parameter1
/100, MOD_ABSOLUTE
);
1464 case 5: // no current hp bonus
1466 BASE_MUL( IE_MAXHITPOINTS
, fx
->Parameter1
);
1468 STAT_MUL( IE_MAXHITPOINTS
, fx
->Parameter1
);
1472 return FX_PERMANENT
;
1475 // 0x13 IntelligenceModifier
1476 int fx_intelligence_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1478 if (0) printf( "fx_intelligence_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1480 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1485 return FX_PERMANENT
;
1488 // 0x14 State:Invisible
1489 // this is more complex, there is a half-invisibility state
1490 // and there is a hidden state
1491 int fx_set_invisible_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1493 switch (fx
->Parameter2
) {
1496 STATE_SET( STATE_PST_INVIS
);
1498 STATE_SET( STATE_INVISIBLE
);
1500 STAT_ADD(IE_TOHIT
, 4);
1503 STATE_SET( STATE_INVIS2
);
1504 HandleBonus(target
, IE_ARMORCLASS
, 4, fx
->TimingMode
);
1509 ieDword Trans
= fx
->Parameter4
;
1510 if (fx
->Parameter3
) {
1523 fx
->Parameter4
=Trans
;
1524 STAT_SET( IE_TRANSLUCENT
, Trans
);
1528 // 0x15 LoreModifier
1529 int fx_lore_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1531 if (0) printf( "fx_lore_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1533 STAT_MOD( IE_LORE
);
1537 // 0x16 LuckModifier
1538 int fx_luck_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1540 if (0) printf( "fx_luck_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1542 STAT_MOD( IE_LUCK
);
1543 STAT_MOD( IE_DAMAGELUCK
);
1547 // 0x17 MoraleModifier
1548 int fx_morale_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1550 if (0) printf( "fx_morale_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1552 STAT_MOD( IE_MORALE
);
1557 int fx_set_panic_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1559 if (0) printf( "fx_set_panic_state (%2d)\n", fx
->Opcode
);
1561 if (target
->HasSpellState(SS_BLOODRAGE
)) {
1562 return FX_NOT_APPLIED
;
1565 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1566 BASE_STATE_SET( STATE_PANIC
);
1568 STATE_SET( STATE_PANIC
);
1570 if (enhanced_effects
) {
1571 target
->AddPortraitIcon(PI_PANIC
);
1573 return FX_PERMANENT
;
1576 // 0x19 State:Poisoned
1577 int fx_set_poisoned_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1579 if (0) printf( "fx_set_poisoned_state (%2d): Damage: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1580 //apparently this bit isn't set, but then why is it here
1581 //this requires a little research
1582 STATE_SET( STATE_POISONED
);
1583 //also this effect is executed every update
1585 int tmp
= fx
->Parameter1
;
1587 HandlePercentageDamage(fx
, target
);
1589 switch(fx
->Parameter2
) {
1591 tmp
*= core
->Time
.round_sec
;
1595 tmp
*= core
->Time
.turn_sec
;
1601 case RPD_PERCENT
: // handled in HandlePercentageDamage
1603 tmp
= 1; // hit points per second
1604 damage
= fx
->Parameter1
;
1612 // all damage is at most per-second
1613 tmp
*= AI_UPDATE_TIME
;
1614 if (tmp
&& (core
->GetGame()->GameTime
%tmp
)) {
1618 Scriptable
*caster
= GetCaster(Owner
, fx
);
1621 target
->Damage(damage
, DAMAGE_POISON
, caster
);
1626 static EffectRef fx_apply_effect_curse_ref
={"ApplyEffectCurse",NULL
,-1};
1627 static EffectRef fx_pst_jumble_curse_ref
={"JumbleCurse",NULL
,-1};
1629 // gemrb extension: if the resource field is filled, it will remove curse only from the specified item
1630 int fx_remove_curse (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1632 if (0) printf( "fx_remove_curse (%2d): Resource: %s Type: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
1634 switch(fx
->Parameter2
)
1637 //this is pst specific
1638 target
->fxqueue
.RemoveAllEffects(fx_pst_jumble_curse_ref
);
1641 Inventory
*inv
= &target
->inventory
;
1642 int i
= target
->inventory
.GetSlotCount();
1644 //does this slot need unequipping
1645 if (core
->QuerySlotEffects(i
) ) {
1646 if (fx
->Resource
[0] && strnicmp(inv
->GetSlotItem(i
)->ItemResRef
, fx
->Resource
,8) ) {
1649 if (!(inv
->GetItemFlag(i
)&IE_INV_ITEM_CURSED
)) {
1652 inv
->ChangeItemFlag(i
, IE_INV_ITEM_CURSED
, BM_NAND
);
1653 if (inv
->UnEquipItem(i
,true)) {
1654 CREItem
*tmp
= inv
->RemoveItem(i
);
1655 if(inv
->AddSlotItem(tmp
,-3)!=ASI_SUCCESS
) {
1656 //if the item couldn't be placed in the inventory, then put it back to the original slot
1657 inv
->SetSlotItem(tmp
,i
);
1658 //and drop it in the area. (If there is no area, then the item will stay in the inventory)
1659 target
->DropItem(i
,0);
1664 target
->fxqueue
.RemoveAllEffects(fx_apply_effect_curse_ref
);
1667 //this is an instant effect
1668 return FX_NOT_APPLIED
;
1671 // 0x1b AcidResistanceModifier
1672 int fx_acid_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1674 if (0) printf( "fx_acid_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1676 STAT_MOD( IE_RESISTACID
);
1680 // 0x1c ColdResistanceModifier
1681 int fx_cold_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1683 if (0) printf( "fx_cold_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1685 STAT_MOD( IE_RESISTCOLD
);
1689 // 0x1d ElectricityResistanceModifier
1690 int fx_electricity_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1692 if (0) printf( "fx_electricity_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1694 STAT_MOD( IE_RESISTELECTRICITY
);
1698 // 0x1e FireResistanceModifier
1699 int fx_fire_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1701 if (0) printf( "fx_fire_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1703 STAT_MOD( IE_RESISTFIRE
);
1707 // 0x1f MagicDamageResistanceModifier
1708 int fx_magic_damage_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1710 if (0) printf( "fx_magic_damage_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1712 STAT_MOD( IE_MAGICDAMAGERESISTANCE
);
1717 int fx_cure_dead_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1719 if (0) printf( "fx_cure_dead_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1720 Point
p(fx
->PosX
, fx
->PosY
);
1721 Resurrect(Owner
, target
, fx
, p
);
1722 return FX_NOT_APPLIED
;
1725 // 0x21 SaveVsDeathModifier
1726 int fx_save_vs_death_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1728 if (0) printf( "fx_save_vs_death_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1730 HandleBonus( target
, IE_SAVEVSDEATH
, fx
->Parameter1
, fx
->TimingMode
);
1734 // 0x22 SaveVsWandsModifier
1735 int fx_save_vs_wands_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1737 if (0) printf( "fx_save_vs_wands_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1739 HandleBonus( target
, IE_SAVEVSWANDS
, fx
->Parameter1
, fx
->TimingMode
);
1743 // 0x23 SaveVsPolyModifier
1744 int fx_save_vs_poly_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1746 if (0) printf( "fx_save_vs_poly_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1748 HandleBonus( target
, IE_SAVEVSPOLY
, fx
->Parameter1
, fx
->TimingMode
);
1752 // 0x24 SaveVsBreathModifier
1753 int fx_save_vs_breath_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1755 if (0) printf( "fx_save_vs_breath_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1757 HandleBonus( target
, IE_SAVEVSBREATH
, fx
->Parameter1
, fx
->TimingMode
);
1761 // 0x25 SaveVsSpellsModifier
1762 int fx_save_vs_spell_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1764 if (0) printf( "fx_save_vs_spell_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1766 HandleBonus( target
, IE_SAVEVSSPELL
, fx
->Parameter1
, fx
->TimingMode
);
1770 // 0x26 State:Silenced
1771 int fx_set_silenced_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1773 if (0) printf( "fx_set_silenced_state (%2d)\n", fx
->Opcode
);
1774 STATE_SET( STATE_SILENCED
);
1778 static EffectRef fx_animation_stance_ref
= {"AnimationStateChange",NULL
,-1};
1780 // 0x27 State:Helpless
1781 // this effect sets both bits, but 'awaken' only removes the sleep bit
1782 // FIXME: this is probably a persistent effect
1783 int fx_set_unconscious_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
1785 if (0) printf( "fx_set_unconscious_state (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
1787 if (target
->HasSpellState(SS_BLOODRAGE
)) {
1788 return FX_NOT_APPLIED
;
1791 if (fx
->FirstApply
) {
1794 newfx
= EffectQueue::CreateEffectCopy(fx
, fx_animation_stance_ref
, 0, IE_ANI_SLEEP
);
1795 core
->ApplyEffect(newfx
, target
, Owner
);
1800 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1801 BASE_STATE_SET( STATE_HELPLESS
| STATE_SLEEP
); //don't awaken on damage
1803 STATE_SET( STATE_HELPLESS
| STATE_SLEEP
); //don't awaken on damage
1804 if (fx
->Parameter2
) {
1805 target
->SetSpellState(SS_NOAWAKE
);
1807 target
->AddPortraitIcon(PI_SLEEP
);
1809 return FX_PERMANENT
;
1812 // 0x28 State:Slowed
1813 // this function removes hasted state, or sets slowed state
1814 static EffectRef fx_set_haste_state_ref
={"State:Hasted",NULL
,-1};
1816 int fx_set_slowed_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1818 if (0) printf( "fx_set_slowed_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1820 //iwd2 free action or aegis disables this effect
1821 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
1822 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
1824 if (STATE_GET(STATE_HASTED
) ) {
1825 BASE_STATE_CURE( STATE_HASTED
);
1826 target
->fxqueue
.RemoveAllEffects( fx_set_haste_state_ref
);
1827 target
->fxqueue
.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref
, PI_HASTED
);
1829 STATE_SET( STATE_SLOWED
);
1830 target
->AddPortraitIcon(PI_SLOWED
);
1831 // halve apr and speed
1832 STAT_MUL(IE_NUMBEROFATTACKS
, 50);
1833 STAT_MUL(IE_MOVEMENTRATE
, 50);
1835 return FX_PERMANENT
;
1839 int fx_sparkle (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1841 if (0) printf( "fx_sparkle (%2d): Sparkle colour: %d ; Sparkle type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1843 return FX_NOT_APPLIED
;
1846 Map
*map
= target
->GetCurrentArea();
1850 Point
p(fx
->PosX
, fx
->PosY
);
1852 map
->Sparkle( fx
->Duration
, fx
->Parameter1
, fx
->Parameter2
, p
, fx
->Parameter3
);
1853 return FX_NOT_APPLIED
;
1856 // 0x2A WizardSpellSlotsModifier
1857 int fx_bonus_wizard_spells (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1859 if (0) printf( "fx_bonus_wizard_spells (%2d): Spell Add: %d ; Spell Level: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1862 //if param2 is 0, then double spells up to param1
1863 if(!fx
->Parameter2
) {
1864 for (unsigned int j
=0;j
<fx
->Parameter1
&& j
<MAX_SPELL_LEVEL
;j
++) {
1865 target
->spellbook
.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD
, j
, true);
1870 //if param2 is 0x200, then double spells at param1
1871 if (fx
->Parameter2
==0x200) {
1872 unsigned int j
= fx
->Parameter1
-1;
1873 if (j
<MAX_SPELL_LEVEL
) {
1874 target
->spellbook
.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD
, j
, true);
1878 for(unsigned int j
=0;j
<MAX_SPELL_LEVEL
;j
++) {
1879 if (fx
->Parameter2
&i
) {
1880 target
->spellbook
.SetMemorizableSpellsCount(fx
->Parameter1
, IE_SPELL_TYPE_WIZARD
, j
, true);
1887 // 0x2B Cure:Petrification
1888 int fx_cure_petrified_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1890 if (0) printf( "fx_cure_petrified_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1891 BASE_STATE_CURE( STATE_PETRIFIED
);
1892 return FX_NOT_APPLIED
;
1895 // 0x2C StrengthModifier
1896 int fx_strength_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1898 if (0) printf( "fx_strength_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1900 ////how strength: value is based on class
1901 if (fx
->Parameter2
==3) {
1902 fx
->Parameter1
= core
->Roll(1,SpellAbilityDieRoll(target
,1),0);
1906 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
1911 return FX_PERMANENT
;
1915 int power_word_stun_iwd2(Actor
*target
, Effect
*fx
)
1917 int hp
= BASE_GET(IE_HITPOINTS
);
1918 if (hp
>150) return FX_NOT_APPLIED
;
1920 if (hp
>100) stuntime
= core
->Roll(1,4,0);
1921 else if (hp
>50) stuntime
= core
->Roll(2,4,0);
1922 else stuntime
= core
->Roll(4,4,0);
1924 fx
->TimingMode
= FX_DURATION_ABSOLUTE
;
1925 fx
->Duration
= stuntime
*6*core
->Time
.round_size
+ core
->GetGame()->GameTime
;
1926 STATE_SET( STATE_STUNNED
);
1927 target
->AddPortraitIcon(PI_STUN
);
1931 int fx_set_stun_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1933 if (0) printf( "fx_set_stun_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1935 //actually the original engine just skips this effect if the target is dead
1936 if ( STATE_GET(STATE_DEAD
) ) {
1937 return FX_NOT_APPLIED
;
1940 //this is an IWD extension
1941 if (target
->HasSpellState(SS_BLOODRAGE
)) {
1942 return FX_NOT_APPLIED
;
1945 if (fx
->Parameter2
==2) {
1946 //don't reroll the duration next time we get here
1947 if (fx
->FirstApply
) {
1948 return power_word_stun_iwd2(target
, fx
);
1951 STATE_SET( STATE_STUNNED
);
1952 target
->AddPortraitIcon(PI_STUN
);
1953 if (fx
->Parameter2
==1) {
1954 target
->SetSpellState(SS_AWAKE
);
1960 static EffectRef fx_set_stun_state_ref
={"State:Stun",NULL
,-1};
1961 static EffectRef fx_hold_creature_no_icon_ref
={"State:HoldNoIcon",NULL
,-1};
1963 int fx_cure_stun_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1965 if (0) printf( "fx_cure_stun_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1966 BASE_STATE_CURE( STATE_STUNNED
);
1967 target
->fxqueue
.RemoveAllEffects(fx_set_stun_state_ref
);
1968 target
->fxqueue
.RemoveAllEffects(fx_hold_creature_no_icon_ref
);
1969 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_HELD
);
1970 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_HOPELESS
);
1971 return FX_NOT_APPLIED
;
1974 // 0x2F Cure:Invisible
1975 // 0x74 Cure:Invisible2
1976 static EffectRef fx_set_invisible_state_ref
={"State:Invisible",NULL
,-1};
1978 int fx_cure_invisible_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1980 if (0) printf( "fx_cure_invisible_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1981 if (!STATE_GET(STATE_NONDET
)) {
1983 BASE_STATE_CURE( STATE_PST_INVIS
);
1985 BASE_STATE_CURE( STATE_INVISIBLE
| STATE_INVIS2
);
1987 target
->fxqueue
.RemoveAllEffects(fx_set_invisible_state_ref
);
1989 return FX_NOT_APPLIED
;
1992 // 0x30 Cure:Silence
1993 static EffectRef fx_set_silenced_state_ref
={"State:Silenced",NULL
,-1};
1995 int fx_cure_silenced_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
1997 if (0) printf( "fx_cure_silenced_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
1998 BASE_STATE_CURE( STATE_SILENCED
);
1999 target
->fxqueue
.RemoveAllEffects(fx_set_silenced_state_ref
);
2000 return FX_NOT_APPLIED
;
2003 // 0x31 WisdomModifier
2004 int fx_wisdom_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2006 if (0) printf( "fx_wisdom_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2008 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
2013 return FX_PERMANENT
;
2016 // 0x32 Color:BriefRGB
2017 int fx_brief_rgb (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2019 if (0) printf( "fx_brief_rgb (%2d): RGB: %d, Location and speed: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2021 int speed
= (fx
->Parameter2
>> 16) & 0xff;
2022 target
->SetColorMod(0xff, RGBModifier::ADD
, speed
,
2023 fx
->Parameter1
>> 8, fx
->Parameter1
>> 16,
2024 fx
->Parameter1
>> 24, 0);
2026 return FX_NOT_APPLIED
;
2029 // 0x33 Color:DarkenRGB
2030 int fx_darken_rgb (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2032 if (0) printf( "fx_darken_rgb (%2d): RGB: %d, Location and speed: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2033 EffectQueue::HackColorEffects(target
, fx
);
2034 ieDword location
= fx
->Parameter2
& 0xff;
2035 target
->SetColorMod(location
, RGBModifier::TINT
, -1, fx
->Parameter1
>> 8,
2036 fx
->Parameter1
>> 16, fx
->Parameter1
>> 24);
2040 // 0x34 Color:GlowRGB
2041 int fx_glow_rgb (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2043 if (0) printf( "fx_glow_rgb (%2d): RGB: %d, Location and speed: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2044 EffectQueue::HackColorEffects(target
, fx
);
2045 ieDword location
= fx
->Parameter2
& 0xff;
2046 target
->SetColorMod(location
, RGBModifier::BRIGHTEN
, -1,
2047 fx
->Parameter1
>> 8, fx
->Parameter1
>> 16,
2048 fx
->Parameter1
>> 24);
2053 // 0x35 AnimationIDModifier
2054 static EffectRef fx_animation_id_modifier_ref
={"AnimationIDModifier",NULL
,-1};
2056 int fx_animation_id_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2058 if (0) printf( "fx_animation_id_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2060 switch (fx
->Parameter2
) {
2061 case 0: //non permanent animation change
2063 STAT_SET( IE_ANIMATION_ID
, fx
->Parameter1
);
2065 case 1: //remove any non permanent change
2066 target
->fxqueue
.RemoveAllEffects(fx_animation_id_modifier_ref
);
2067 //return FX_NOT_APPLIED;
2068 //intentionally passing through (perma change removes previous changes)
2069 case 2: //permanent animation id change
2070 target
->SetBaseNoPCF(IE_ANIMATION_ID
, fx
->Parameter1
);
2071 return FX_NOT_APPLIED
;
2075 // 0x36 ToHitModifier
2076 int fx_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2078 if (0) printf( "fx_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2080 HandleBonus( target
, IE_TOHIT
, fx
->Parameter1
, fx
->TimingMode
);
2084 // 0x37 KillCreatureType
2085 static EffectRef fx_death_ref
={"Death",NULL
,-1};
2087 int fx_kill_creature_type (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2089 if (0) printf( "fx_kill_creature_type (%2d): Value: %d, IDS: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2090 if (EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
2091 //convert it to a death opcode or apply the new effect?
2092 fx
->Opcode
= EffectQueue::ResolveEffect(fx_death_ref
);
2093 fx
->TimingMode
= FX_DURATION_INSTANT_PERMANENT
;
2099 return FX_NOT_APPLIED
;
2102 // 0x38 Alignment:Invert
2103 //switch good to evil and evil to good
2104 //also switch chaotic to lawful and vice versa
2105 //gemrb extension: param2 actually controls which parts should be reversed
2106 // 0 - switch both (as original)
2107 // 1 - switch good and evil
2108 // 2 - switch lawful and chaotic
2110 static int al_switch_both
[16]={0,0x33,0x32,0x31,0,0x23,0x22,0x21,0,0x13,0x12,0x11};
2111 static int al_switch_law
[16]={0,0x31,0x32,0x33,0,0x21,0x22,0x23,0,0x11,0x12,0x13};
2112 static int al_switch_good
[16]={0,0x13,0x12,0x11,0,0x23,0x22,0x21,0,0x33,0x32,0x31};
2113 int fx_alignment_invert (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2115 if (0) printf( "fx_alignment_invert (%2d)\n", fx
->Opcode
);
2116 register ieDword newalign
= target
->GetStat( IE_ALIGNMENT
);
2117 //compress the values. GNE is the first 2 bits originally
2118 //LNC is the 4/5. bits.
2119 newalign
= (newalign
& AL_GE_MASK
) | ((newalign
& AL_LC_MASK
)>>2);
2120 switch (fx
->Parameter2
) {
2122 newalign
= al_switch_both
[newalign
];
2124 case 1: //switch good/evil
2125 newalign
= al_switch_good
[newalign
];
2128 newalign
= al_switch_law
[newalign
];
2131 STAT_SET( IE_ALIGNMENT
, newalign
);
2135 // 0x39 Alignment:Change
2136 int fx_alignment_change (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2138 if (0) printf( "fx_alignment_change (%2d): Value: %d\n", fx
->Opcode
, fx
->Parameter2
);
2139 STAT_SET( IE_ALIGNMENT
, fx
->Parameter2
);
2143 // 0x3a DispelEffects
2144 int fx_dispel_effects (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2146 if (0) printf( "fx_dispel_effects (%2d): Value: %d, IDS: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2150 switch (fx
->Parameter2
) {
2156 //same level: 50% success, each diff modifies it by 5%
2157 level
= core
->Roll(1,20,fx
->Power
-10);
2158 if (level
>=0x80000000) level
= 0;
2161 //same level: 50% success, each diff modifies it by 5%
2162 level
= core
->Roll(1,20,fx
->Parameter1
-10);
2163 if (level
>=0x80000000) level
= 0;
2166 //if signed would it be negative?
2167 target
->fxqueue
.RemoveLevelEffects(Removed
, level
, RL_DISPELLABLE
, 0);
2168 return FX_NOT_APPLIED
;
2171 // 0x3B StealthModifier
2172 int fx_stealth_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2174 if (0) printf( "fx_stealth_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2176 STAT_MOD( IE_STEALTH
);
2180 // 0x3C MiscastMagicModifier
2181 int fx_miscast_magic_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2183 if (0) printf( "fx_miscast_magic_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2185 switch (fx
->Parameter2
) {
2187 STAT_SET( IE_DEADMAGIC
, 1);
2189 STAT_SET( IE_SPELLFAILUREMAGE
, fx
->Parameter1
);
2192 STAT_SET( IE_DEADMAGIC
, 1);
2194 STAT_SET( IE_SPELLFAILUREPRIEST
, fx
->Parameter1
);
2197 STAT_SET( IE_DEADMAGIC
, 1);
2199 STAT_SET( IE_SPELLFAILUREINNATE
, fx
->Parameter1
);
2202 return FX_NOT_APPLIED
;
2207 // 0x3D AlchemyModifier
2208 // this crashes in bg2 due to assertion failure (disabled intentionally)
2209 // and in iwd it doesn't really follow the stat_mod convention (quite lame)
2210 int fx_alchemy_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2212 if (0) printf( "fx_alchemy_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2214 switch(fx
->Parameter2
) {
2216 STAT_ADD( IE_ALCHEMY
, fx
->Parameter1
);
2219 STAT_SET( IE_ALCHEMY
, fx
->Parameter1
);
2222 STAT_SET( IE_ALCHEMY
, 100 );
2228 // 0x3E PriestSpellSlotsModifier
2229 int fx_bonus_priest_spells (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2231 if (0) printf( "fx_bonus_priest_spells (%2d): Spell Add: %d ; Spell Level: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2234 //if param2 is 0, then double spells up to param1
2235 if(!fx
->Parameter2
) {
2236 for (unsigned int j
=0;j
<fx
->Parameter1
&& j
<MAX_SPELL_LEVEL
;j
++) {
2237 target
->spellbook
.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_PRIEST
, j
, true);
2243 //if param2 is 0x200, then double spells at param1
2244 if (fx
->Parameter2
==0x200) {
2245 unsigned int j
= fx
->Parameter1
-1;
2246 target
->spellbook
.SetMemorizableSpellsCount(fx
->Parameter1
, IE_SPELL_TYPE_PRIEST
, j
, true);
2250 for(unsigned int j
=0;j
<MAX_SPELL_LEVEL
;j
++) {
2251 if (fx
->Parameter2
&i
) {
2252 target
->spellbook
.SetMemorizableSpellsCount(fx
->Parameter1
, IE_SPELL_TYPE_PRIEST
, j
, true);
2259 // 0x3F State:Infravision
2260 int fx_set_infravision_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2262 if (0) printf( "fx_set_infravision_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2263 STATE_SET( STATE_INFRA
);
2267 // 0x40 Cure:Infravision
2268 static EffectRef fx_set_infravision_state_ref
={"State:Infravision",NULL
,-1};
2270 int fx_cure_infravision_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2272 if (0) printf( "fx_cure_infravision_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2273 BASE_STATE_CURE( STATE_INFRA
);
2274 target
->fxqueue
.RemoveAllEffects(fx_set_infravision_state_ref
);
2275 return FX_NOT_APPLIED
;
2279 int fx_set_blur_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2281 if (0) printf( "fx_set_blur_state (%2d)\n", fx
->Opcode
);
2282 //death stops this effect
2283 if (STATE_GET( STATE_DEAD
) ) {
2284 return FX_NOT_APPLIED
;
2286 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
2287 BASE_STATE_SET( STATE_BLUR
);
2289 STATE_SET( STATE_BLUR
);
2292 if (enhanced_effects
) {
2293 target
->AddPortraitIcon(PI_BLUR
);
2295 return FX_PERMANENT
;
2298 // 0x42 TransparencyModifier
2299 int fx_transparency_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2301 if (0) printf( "fx_transparency_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2303 //maybe this needs some timing
2304 switch (fx
->Parameter2
) {
2306 if (fx
->Parameter1
<255) {
2307 if (core
->GetGame()->GameTime
%2) {
2313 if (fx
->Parameter1
) {
2314 if (core
->GetGame()->GameTime
%2) {
2320 STAT_MOD( IE_TRANSLUCENT
);
2324 // 0x43 SummonCreature
2326 static int eamods
[]={EAM_ALLY
,EAM_ALLY
,EAM_DEFAULT
,EAM_ALLY
,EAM_DEFAULT
,EAM_ENEMY
,EAM_ALLY
};
2328 int fx_summon_creature (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
2330 if (0) printf( "fx_summon_creature (%2d): ResRef:%s Anim:%s Type: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Resource2
, fx
->Parameter2
);
2332 return FX_NOT_APPLIED
;
2335 if (!target
->GetCurrentArea()) {
2339 //summon creature (resource), play vvc (resource2)
2340 //creature's lastsummoner is Owner
2341 //creature's target is target
2342 //position of appearance is target's pos
2344 if (fx
->Parameter2
<6){
2345 eamod
= eamods
[fx
->Parameter2
];
2348 //the monster should appear near the effect position
2349 Point
p(fx
->PosX
, fx
->PosY
);
2351 Effect
*newfx
= EffectQueue::CreateUnsummonEffect(fx
);
2352 core
->SummonCreature(fx
->Resource
, fx
->Resource2
, Owner
, target
, p
, eamod
, 0, newfx
);
2354 return FX_NOT_APPLIED
;
2357 // 0x44 UnsummonCreature
2358 int fx_unsummon_creature (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2360 if (0) printf( "fx_unsummon_creature (%2d)\n", fx
->Opcode
);
2362 //to be compatible with the original engine, unsummon doesn't work with PC's
2363 //but it works on anything else
2364 if (!target
->InParty
) {
2365 //play the vanish animation
2366 ScriptedAnimation
* sca
= gamedata
->GetScriptedAnimation(fx
->Resource
, false);
2368 sca
->XPos
+=target
->Pos
.x
;
2369 sca
->YPos
+=target
->Pos
.y
;
2370 target
->GetCurrentArea()->AddVVCell(sca
);
2372 //remove the creature
2373 target
->DestroySelf();
2375 return FX_NOT_APPLIED
;
2378 // 0x45 State:Nondetection
2379 int fx_set_nondetection_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2381 if (0) printf( "fx_set_nondetection_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2382 STATE_SET( STATE_NONDET
);
2386 // 0x46 Cure:Nondetection
2387 static EffectRef fx_set_nondetection_state_ref
={"State:Nondetection",NULL
,-1};
2389 int fx_cure_nondetection_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2391 if (0) printf( "fx_cure_nondetection_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2392 BASE_STATE_CURE( STATE_NONDET
);
2393 target
->fxqueue
.RemoveAllEffects(fx_set_nondetection_state_ref
);
2394 return FX_NOT_APPLIED
;
2398 int fx_sex_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2400 if (0) printf( "fx_sex_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2402 if (fx
->Parameter2
) {
2403 value
= fx
->Parameter1
;
2405 if (STAT_GET(IE_SEX_CHANGED
)) {
2406 return FX_NOT_APPLIED
;
2408 STAT_SET( IE_SEX_CHANGED
, 1);
2409 value
= STAT_GET(IE_SEX
);
2410 if (value
==SEX_MALE
) {
2416 STAT_SET( IE_SEX
, value
);
2420 // 0x48 AIIdentifierModifier
2421 int fx_ids_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2423 if (0) printf( "fx_ids_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2424 switch (fx
->Parameter2
) {
2426 STAT_SET(IE_EA
, fx
->Parameter1
);
2429 STAT_SET(IE_GENERAL
, fx
->Parameter1
);
2432 STAT_SET(IE_RACE
, fx
->Parameter1
);
2435 STAT_SET(IE_CLASS
, fx
->Parameter1
);
2438 STAT_SET(IE_SPECIFIC
, fx
->Parameter1
);
2441 STAT_SET(IE_SEX
, fx
->Parameter1
);
2444 STAT_SET(IE_ALIGNMENT
, fx
->Parameter1
);
2447 return FX_NOT_APPLIED
;
2449 //not sure, need a check if this action could be permanent
2453 // 0x49 DamageBonusModifier
2454 int fx_damage_bonus_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2456 if (0) printf( "fx_damage_bonus_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2458 STAT_MOD( IE_DAMAGEBONUS
);
2463 int fx_set_blind_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2465 if (0) printf( "fx_set_blind_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2467 //don't do this effect twice (bug exists in BG2, but fixed in IWD2)
2468 if (!STATE_GET(STATE_BLIND
)) {
2469 STATE_SET( STATE_BLIND
);
2470 //the feat normally exists only in IWD2, but won't hurt
2471 if (!target
->GetFeat(FEAT_BLIND_FIGHT
)) {
2472 STAT_SUB (IE_TOHIT
, 10); // all other tohit stats are treated as bonuses
2479 static EffectRef fx_set_blind_state_ref
={"State:Blind",NULL
,-1};
2481 int fx_cure_blind_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2483 if (0) printf( "fx_cure_blind_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2484 BASE_STATE_CURE( STATE_BLIND
);
2485 target
->fxqueue
.RemoveAllEffects(fx_set_blind_state_ref
);
2486 return FX_NOT_APPLIED
;
2489 // 0x4c State:Feeblemind
2490 int fx_set_feebleminded_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2492 if (0) printf( "fx_set_feebleminded_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2493 STATE_SET( STATE_FEEBLE
);
2494 STAT_SET( IE_INT
, 3);
2495 if (enhanced_effects
) {
2496 target
->AddPortraitIcon(PI_FEEBLEMIND
);
2501 // 0x4d Cure:Feeblemind
2502 static EffectRef fx_set_feebleminded_state_ref
={"State:Feeblemind",NULL
,-1};
2504 int fx_cure_feebleminded_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2506 if (0) printf( "fx_cure_feebleminded_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2507 BASE_STATE_CURE( STATE_FEEBLE
);
2508 target
->fxqueue
.RemoveAllEffects(fx_set_feebleminded_state_ref
);
2509 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_FEEBLEMIND
);
2510 return FX_NOT_APPLIED
;
2513 // 0x4e State:Diseased
2514 int fx_set_diseased_state (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
2516 if (0) printf( "fx_set_diseased_state (%2d): Damage: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2517 if (STATE_GET(STATE_DEAD
|STATE_PETRIFIED
|STATE_FROZEN
) ) {
2518 return FX_NOT_APPLIED
;
2521 //setting damage to 0 because not all types do damage
2524 HandlePercentageDamage(fx
, target
);
2526 switch(fx
->Parameter2
) {
2529 if (fx
->Parameter1
&& (core
->GetGame()->GameTime
%(fx
->Parameter1
*AI_UPDATE_TIME
))) {
2533 case RPD_PERCENT
: // handled in HandlePercentageDamage
2535 damage
= fx
->Parameter1
;
2537 if (core
->GetGame()->GameTime
%AI_UPDATE_TIME
) {
2541 case RPD_STR
: //strength
2542 STAT_ADD(IE_STR
, fx
->Parameter1
);
2545 STAT_ADD(IE_DEX
, fx
->Parameter1
);
2548 STAT_ADD(IE_CON
, fx
->Parameter1
);
2551 STAT_ADD(IE_INT
, fx
->Parameter1
);
2554 STAT_ADD(IE_WIS
, fx
->Parameter1
);
2557 STAT_ADD(IE_CHR
, fx
->Parameter1
);
2559 case RPD_SLOW
: //slow
2566 Scriptable
*caster
= GetCaster(Owner
, fx
);
2569 target
->Damage(damage
, DAMAGE_POISON
, caster
);
2575 // 0x4f Cure:Disease
2576 static EffectRef fx_diseased_state_ref
={"State:Diseased",NULL
,-1};
2578 int fx_cure_diseased_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2580 if (0) printf( "fx_cure_diseased_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2581 //STATE_CURE( STATE_DISEASED ); //the bit flagged as disease is actually the active state. so this is even more unlikely to be used as advertised
2582 target
->fxqueue
.RemoveAllEffects( fx_diseased_state_ref
); //this is what actually happens in bg2
2583 return FX_NOT_APPLIED
;
2586 // 0x50 State:Deafness
2587 // gemrb extension: modifiable amount
2588 // none of the engines care about stacking
2589 int fx_set_deaf_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2591 if (0) printf( "fx_set_deaf_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2594 if (target
->SetSpellState(SS_DEAF
)) return FX_APPLIED
;
2596 if (!fx
->Parameter1
) {
2597 fx
->Parameter1
= 50;
2599 STAT_ADD(IE_SPELLFAILUREMAGE
, fx
->Parameter1
);
2600 if (!fx
->Parameter2
) {
2601 fx
->Parameter1
= 50;
2603 STAT_ADD(IE_SPELLFAILUREPRIEST
, fx
->Parameter2
);
2604 EXTSTATE_SET(EXTSTATE_DEAF
); //iwd1/how needs this
2605 if (enhanced_effects
) {
2606 target
->AddPortraitIcon(PI_DEAFNESS
);
2611 int fx_set_deaf_state_iwd2 (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2613 if (0) printf( "fx_set_deaf_state_iwd2 (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2616 if (target
->SetSpellState(SS_DEAF
)) return FX_APPLIED
;
2618 if (!fx
->Parameter1
) {
2619 //this is a bad hack
2620 fx
->Parameter1
= 20;
2622 STAT_ADD(IE_SPELLFAILUREMAGE
, fx
->Parameter1
);
2623 if (!fx
->Parameter2
) {
2624 fx
->Parameter1
= 20;
2626 STAT_ADD(IE_SPELLFAILUREPRIEST
, fx
->Parameter2
);
2627 EXTSTATE_SET(EXTSTATE_DEAF
); //iwd1/how needs this
2628 target
->AddPortraitIcon(PI_DEAFNESS
); //iwd2 specific
2632 // 0x51 Cure:Deafness
2633 static EffectRef fx_deaf_state_ref
={"State:Deafness",NULL
,-1};
2634 static EffectRef fx_deaf_state_iwd2_ref
={"State:DeafnessIWD2",NULL
,-1};
2636 //removes the deafness effect
2637 int fx_cure_deaf_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2639 if (0) printf( "fx_cure_deaf_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2641 target
->fxqueue
.RemoveAllEffects(fx_deaf_state_ref
);
2642 target
->fxqueue
.RemoveAllEffects(fx_deaf_state_iwd2_ref
);
2643 return FX_NOT_APPLIED
;
2647 int fx_set_ai_script (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2649 if (0) printf( "fx_set_ai_state (%2d): Resource: %s, Type: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
2650 target
->SetScript (fx
->Resource
, fx
->Parameter2
);
2651 return FX_NOT_APPLIED
;
2654 // 0x53 Protection:Projectile
2655 int fx_protection_from_projectile (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2657 if (0) printf( "fx_protection_from_projectile (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
2658 STAT_BIT_OR( IE_IMMUNITY
, IMM_PROJECTILE
);
2662 // 0x54 MagicalFireResistanceModifier
2663 int fx_magical_fire_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2665 if (0) printf( "fx_magical_fire_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2667 STAT_MOD( IE_RESISTMAGICFIRE
);
2671 // 0x55 MagicalColdResistanceModifier
2672 int fx_magical_cold_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2674 if (0) printf( "fx_magical_cold_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2676 STAT_MOD( IE_RESISTMAGICCOLD
);
2680 // 0x56 SlashingResistanceModifier
2681 int fx_slashing_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2683 if (0) printf( "fx_slashing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2685 STAT_MOD( IE_RESISTSLASHING
);
2689 // 0x57 CrushingResistanceModifier
2690 int fx_crushing_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2692 if (0) printf( "fx_crushing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2694 STAT_MOD( IE_RESISTCRUSHING
);
2698 // 0x58 PiercingResistanceModifier
2699 int fx_piercing_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2701 if (0) printf( "fx_piercing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2703 STAT_MOD( IE_RESISTPIERCING
);
2707 // 0x59 MissilesResistanceModifier
2708 int fx_missiles_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2710 if (0) printf( "fx_missiles_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2712 STAT_MOD( IE_RESISTMISSILE
);
2716 // 0x5A OpenLocksModifier
2717 int fx_open_locks_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2719 if (0) printf( "fx_open_locks_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2721 STAT_MOD( IE_LOCKPICKING
);
2725 // 0x5B FindTrapsModifier
2726 int fx_find_traps_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2728 if (0) printf( "fx_find_traps_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2730 STAT_MOD( IE_TRAPS
);
2734 // 0x5C PickPocketsModifier
2735 int fx_pick_pockets_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2737 if (0) printf( "fx_pick_pockets_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2739 STAT_MOD( IE_PICKPOCKET
);
2743 // 0x5D FatigueModifier
2744 int fx_fatigue_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2746 if (0) printf( "fx_fatigue_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2748 STAT_MOD( IE_FATIGUE
);
2749 // TODO: fatigue has a negative effect on luck -> add fatigmod.2da support
2753 // 0x5E IntoxicationModifier
2754 int fx_intoxication_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2756 if (0) printf( "fx_intoxication_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2758 STAT_MOD( IE_INTOXICATION
);
2762 // 0x5F TrackingModifier
2763 int fx_tracking_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2765 if (0) printf( "fx_tracking_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2767 STAT_MOD( IE_TRACKING
);
2771 // 0x60 LevelModifier
2772 int fx_level_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2774 if (0) printf( "fx_level_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2776 STAT_MOD( IE_LEVEL
);
2780 // 0x61 StrengthBonusModifier
2781 int fx_strength_bonus_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2783 if (0) printf( "fx_strength_bonus_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2785 STAT_MOD( IE_STREXTRA
);
2789 // 0x62 State:Regenerating
2790 int fx_set_regenerating_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2792 if (0) printf( "fx_set_regenerating_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2794 int tmp
= fx
->Parameter1
;
2795 ieDword gameTime
= core
->GetGame()->GameTime
;
2798 if (!fx
->Parameter3
) {
2799 //hack to ensure our first call gets through
2800 nextHeal
= gameTime
-1;
2802 nextHeal
= fx
->Parameter3
;
2805 //we can have multiple calls at the same gameTime, so we
2806 //just go to gameTime+1 to ensure one call
2807 if (nextHeal
>=gameTime
) return FX_APPLIED
;
2809 HandlePercentageDamage(fx
, target
);
2811 switch(fx
->Parameter2
) {
2812 case RPD_TURNS
: //restore param3 hp every param1 turns
2813 tmp
*= core
->Time
.rounds_per_turn
;
2815 case RPD_ROUNDS
: //restore param3 hp every param1 rounds
2816 tmp
*= core
->Time
.round_sec
;
2818 case RPD_SECONDS
: //restore param3 hp every param1 seconds
2819 fx
->Parameter3
= nextHeal
+ tmp
*AI_UPDATE_TIME
;
2822 case RPD_PERCENT
: // handled in HandlePercentageDamage
2823 case RPD_POINTS
: //restore param1 hp every second? that's crazy!
2824 damage
= fx
->Parameter1
;
2825 fx
->Parameter3
= nextHeal
+ AI_UPDATE_TIME
;
2828 fx
->Parameter3
= nextHeal
+ AI_UPDATE_TIME
;
2833 //This should take care of the change of the modified stat
2834 //So there is no need to do anything else here other than increasing
2835 //the base current hp
2836 target
->NewBase(IE_HITPOINTS
, damage
, MOD_ADDITIVE
);
2839 // 0x63 SpellDurationModifier
2840 int fx_spell_duration_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2842 if (0) printf( "fx_spell_duration_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2844 switch (fx
->Parameter2
) {
2846 STAT_SET( IE_SPELLDURATIONMODMAGE
, fx
->Parameter1
);
2849 STAT_SET( IE_SPELLDURATIONMODPRIEST
, fx
->Parameter1
);
2852 return FX_NOT_APPLIED
;
2856 // 0x64 Protection:Creature
2857 int fx_generic_effect (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
2859 if (0) printf( "fx_generic_effect (%2d): Param1: %d, Param2: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2863 // 0x65 Protection:Opcode
2864 int fx_protection_opcode (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2866 if (0) printf( "fx_protection_opcode (%2d): Opcode: %d\n", fx
->Opcode
, fx
->Parameter2
);
2867 STAT_BIT_OR(IE_IMMUNITY
, IMM_OPCODE
);
2871 // 0x66 Protection:SpellLevel
2872 int fx_protection_spelllevel (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2874 if (0) printf( "fx_protection_spelllevel (%2d) Level: %d\n", fx
->Opcode
, fx
->Parameter1
);
2876 int value
= fx
->Parameter1
;
2878 STAT_BIT_OR(IE_MINORGLOBE
, 1<<value
);
2879 STAT_BIT_OR(IE_IMMUNITY
, IMM_LEVEL
);
2882 return FX_NOT_APPLIED
;
2886 int fx_change_name (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2888 if (0) printf( "fx_change_name_modifier (%2d): StrRef: %d\n", fx
->Opcode
, fx
->Parameter1
);
2889 target
->SetName(fx
->Parameter1
, 0);
2890 return FX_NOT_APPLIED
;
2893 // 0x68 ExperienceModifier
2894 int fx_experience_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2896 if (0) printf( "fx_experience_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2897 //i believe this has mode too
2898 target
->AddExperience (fx
->Parameter1
);
2899 return FX_NOT_APPLIED
;
2902 // 0x69 GoldModifier
2903 //in BG2 this effect subtracts gold when type is MOD_ADDITIVE
2904 //no one uses it, though. To keep the function, the default branch will do the subtraction
2905 int fx_gold_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2907 if (0) printf( "fx_gold_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2908 if (!target
->InParty
) {
2909 STAT_MOD( IE_GOLD
);
2910 return FX_NOT_APPLIED
;
2913 Game
*game
= core
->GetGame();
2914 //for party members, the gold is stored in the game object
2915 switch( fx
->Parameter2
) {
2917 gold
= fx
->Parameter1
;
2920 gold
= fx
->Parameter1
-game
->PartyGold
;
2923 gold
= game
->PartyGold
*fx
->Parameter1
/100-game
->PartyGold
;
2926 gold
= (ieDword
) -fx
->Parameter1
;
2929 game
->AddGold (gold
);
2930 return FX_NOT_APPLIED
;
2933 // 0x6a MoraleBreakModifier
2934 int fx_morale_break_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2936 if (0) printf( "fx_morale_break_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2937 STAT_MOD(IE_MORALEBREAK
);
2938 return FX_PERMANENT
; //permanent morale break doesn't stick
2941 // 0x6b PortraitChange
2942 int fx_portrait_change (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2944 if (0) printf( "fx_portrait_change (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2945 target
->SetPortrait( fx
->Resource
, fx
->Parameter2
);
2946 return FX_NOT_APPLIED
;
2949 // 0x6c ReputationModifier
2950 int fx_reputation_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2952 if (0) printf( "fx_reputation_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
2953 STAT_MOD(IE_REPUTATION
);
2954 return FX_NOT_APPLIED
; //needs testing
2957 // 0x6d --> see later
2959 // 0x6e works only in PST, reused for turning undead
2961 // 0x6f Item:CreateMagic
2963 static EffectRef fx_remove_item_ref
={"Item:Remove",NULL
,-1};
2965 int fx_create_magic_item (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2967 //charge count is incorrect
2968 target
->inventory
.SetSlotItemRes(fx
->Resource
, target
->inventory
.GetMagicSlot(),fx
->Parameter1
,fx
->Parameter3
,fx
->Parameter4
);
2970 target
->inventory
.SetEquippedSlot(target
->inventory
.GetMagicSlot()-target
->inventory
.GetWeaponSlot(), 0);
2971 if ((fx
->TimingMode
&0xff) == FX_DURATION_INSTANT_LIMITED
) {
2972 //if this effect has expiration, then it will remain as a remove_item
2973 //on the effect queue, inheriting all the parameters
2974 fx
->Opcode
=EffectQueue::ResolveEffect(fx_remove_item_ref
);
2975 fx
->TimingMode
=FX_DURATION_DELAY_PERMANENT
;
2978 return FX_NOT_APPLIED
;
2982 int fx_remove_item (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2984 //will destroy the first item
2985 if (target
->inventory
.DestroyItem(fx
->Resource
,0,1)) {
2986 target
->ReinitQuickSlots();
2988 return FX_NOT_APPLIED
;
2992 int fx_equip_item (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
2994 int eff
= core
->QuerySlotEffects( fx
->Parameter2
);
2996 case SLOT_EFFECT_NONE
:
2997 case SLOT_EFFECT_MELEE
:
2998 target
->inventory
.SetEquippedSlot( fx
->Parameter2
, fx
->Parameter1
);
3001 target
->inventory
.EquipItem( fx
->Parameter2
);
3004 target
->ReinitQuickSlots();
3005 return FX_NOT_APPLIED
;
3009 int fx_dither (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
3011 if (0) printf( "fx_dither (%2d): Value: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3012 //this effect doesn't work in any engine versions
3013 return FX_NOT_APPLIED
;
3016 // 0x73 DetectAlignment
3017 //gemrb extension: chaotic/lawful detection
3018 int fx_detect_alignment (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3022 static int ge
[] = {AL_EVIL
, AL_GE_NEUTRAL
, AL_GOOD
, AL_CHAOTIC
, AL_LC_NEUTRAL
, AL_LAWFUL
};
3024 msk
= ge
[fx
->Parameter2
];
3025 if (fx
->Parameter2
<3) {
3027 stat
= target
->GetStat(IE_ALIGNMENT
)&AL_GE_MASK
;
3030 //3,4,5 -> 0x30, 0x20, 0x10
3031 stat
= target
->GetStat(IE_ALIGNMENT
)&AL_LC_MASK
;
3033 if (stat
!= msk
) return FX_NOT_APPLIED
;
3035 ieDword color
= fx
->Parameter1
;
3038 if (!color
) color
= 0xff0000;
3039 displaymsg
->DisplayConstantStringName(STR_EVIL
, color
, target
);
3041 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0xff, 0, 0, 0);
3044 if (!color
) color
= 0xff00;
3045 displaymsg
->DisplayConstantStringName(STR_GOOD
, color
, target
);
3047 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0, 0xff, 0, 0);
3050 if (!color
) color
= 0xff;
3051 displaymsg
->DisplayConstantStringName(STR_GE_NEUTRAL
, color
, target
);
3053 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0, 0, 0xff, 0);
3056 if (!color
) color
= 0xff00ff;
3057 displaymsg
->DisplayConstantStringName(STR_CHAOTIC
, color
, target
);
3059 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0xff, 0, 0xff, 0);
3062 if (!color
) color
= 0xffffff;
3063 displaymsg
->DisplayConstantStringName(STR_LAWFUL
, color
, target
);
3065 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0xff, 0xff, 0xff, 0);
3068 if (!color
) color
= 0xff;
3069 displaymsg
->DisplayConstantStringName(STR_LC_NEUTRAL
, color
, target
);
3071 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0, 0, 0xff, 0);
3074 return FX_NOT_APPLIED
;
3077 // 0x74 Cure:Invisible2 (see 0x2f)
3080 // 0 reveal whole area
3081 // 1 reveal area in pattern
3082 int fx_reveal_area (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3084 if (0) printf( "fx_reveal_area (%2d): Value: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3085 Map
*map
= target
->GetCurrentArea();
3090 if (fx
->Parameter2
) {
3091 map
->Explore(fx
->Parameter1
);
3095 return FX_NOT_APPLIED
;
3098 // 0x76 Reveal:Creatures
3099 int fx_reveal_creatures (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
3101 if (0) printf( "fx_reveal_creatures (%2d): Value: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3102 //reveals creatures (not working in original IE)
3103 return FX_NOT_APPLIED
;
3107 static EffectRef fx_mirror_image_modifier_ref
={"MirrorImageModifier",NULL
,-1};
3109 int fx_mirror_image (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
3111 if (0) printf( "fx_mirror_image (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3114 if (fx
->Parameter2
) {
3115 images
= 1; //reflection
3118 // the original uses only IE_LEVEL, but that can be awefully bad in
3119 // the case of dual- and multiclasses
3120 unsigned int level
= target
->GetMageLevel();
3121 if (!level
) level
= target
->GetSorcererLevel();
3122 if (!level
) level
= target
->GetBardLevel();
3123 if (!level
) level
= target
->GetStat(IE_LEVEL
);
3124 // 2-8 mirror images
3125 images
= level
/3 + 2;
3126 if (images
> 8) images
= 8;
3129 Effect
*fx2
= target
->fxqueue
.HasEffect(fx_mirror_image_modifier_ref
);
3131 //update old effect with our numbers if our numbers are more
3132 if (fx2
->Parameter1
<images
) {
3133 fx2
->Parameter1
=images
;
3135 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
) {
3136 fx2
->TimingMode
= FX_DURATION_INSTANT_PERMANENT
;
3138 return FX_NOT_APPLIED
;
3140 fx
->Opcode
= EffectQueue::ResolveEffect(fx_mirror_image_modifier_ref
);
3141 fx
->Parameter1
=images
;
3142 //parameter2 could be 0 or 1 (mirror image or reflection)
3143 //execute the translated effect
3144 return fx_mirror_image_modifier(Owner
, target
, fx
);
3147 // 0x78 Protection:Weapons
3148 int fx_immune_to_weapon (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
3150 if (0) printf( "fx_immune_to_weapon (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3151 if (!fx
->FirstApply
) return FX_APPLIED
;
3154 ieDword mask
, value
;
3159 switch(fx
->Parameter2
) {
3160 case 0: //enchantment level
3161 level
= fx
->Parameter1
;
3163 case 1: //all magical weapons
3164 value
= IE_INV_ITEM_MAGICAL
;
3166 case 2: //all nonmagical weapons
3167 mask
= IE_INV_ITEM_MAGICAL
;
3169 case 3: //all silver weapons
3170 value
= IE_INV_ITEM_SILVER
;
3172 case 4: //all non silver weapons
3173 mask
= IE_INV_ITEM_SILVER
;
3176 value
= IE_INV_ITEM_SILVER
;
3177 mask
= IE_INV_ITEM_SILVER
;
3180 case 6: //all twohanded
3181 value
= IE_INV_ITEM_TWOHANDED
;
3183 case 7: //all not twohanded
3184 mask
= IE_INV_ITEM_TWOHANDED
;
3186 case 8: //all twohanded
3187 value
= IE_INV_ITEM_CURSED
;
3189 case 9: //all not twohanded
3190 mask
= IE_INV_ITEM_CURSED
;
3192 case 10: //all twohanded
3193 value
= IE_INV_ITEM_COLDIRON
;
3195 case 11: //all not twohanded
3196 mask
= IE_INV_ITEM_COLDIRON
;
3199 mask
= fx
->Parameter1
;
3201 value
= fx
->Parameter1
;
3206 fx
->Parameter1
= (ieDword
) level
; //putting the corrected value back
3207 fx
->Parameter3
= mask
;
3208 fx
->Parameter4
= value
;
3212 // 0x79 VisualAnimationEffect (unknown)
3213 int fx_visual_animation_effect (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
3215 //this is an unknown effect
3216 if (0) printf( "fx_visual_animation_effect (%2d)\n", fx
->Opcode
);
3217 return FX_NOT_APPLIED
;
3220 // 0x7a Item:CreateInventory
3221 static EffectRef fx_remove_inventory_item_ref
={"Item:RemoveInventory",NULL
,-1};
3223 int fx_create_inventory_item (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3225 if (0) printf( "fx_create_inventory_item (%2d)\n", fx
->Opcode
);
3226 target
->inventory
.AddSlotItemRes( fx
->Resource
, SLOT_ONLYINVENTORY
, fx
->Parameter1
, fx
->Parameter3
, fx
->Parameter4
);
3227 if ((fx
->TimingMode
&0xff) == FX_DURATION_INSTANT_LIMITED
) {
3228 //if this effect has expiration, then it will remain as a remove_item
3229 //on the effect queue, inheriting all the parameters
3230 fx
->Opcode
=EffectQueue::ResolveEffect(fx_remove_inventory_item_ref
);
3231 fx
->TimingMode
=FX_DURATION_DELAY_PERMANENT
;
3234 return FX_NOT_APPLIED
;
3237 // 0x7b Item:RemoveInventory
3238 int fx_remove_inventory_item (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3240 if (0) printf( "fx_remove_inventory_item (%2d)\n", fx
->Opcode
);
3241 //FIXME: now equipped items are only wielded weapons
3242 //why would it not let equipped items to be destructed?
3243 target
->inventory
.DestroyItem(fx
->Resource
,IE_INV_ITEM_EQUIPPED
,1);
3244 return FX_NOT_APPLIED
;
3247 // 0x7c DimensionDoor
3248 // iwd2 has several options
3249 int fx_dimension_door (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
3251 if (0) printf( "fx_dimension_door (%2d) Type:%d\n", fx
->Opcode
, fx
->Parameter2
);
3254 switch(fx
->Parameter2
)
3256 case 0: //target to point
3260 case 1: //owner to target
3261 if (Owner
->Type
!=ST_ACTOR
) {
3262 return FX_NOT_APPLIED
;
3265 target
= (Actor
*) Owner
;
3267 case 2: //target to saved location
3268 p
.x
=STAT_GET(IE_SAVEDXPOS
);
3269 p
.x
=STAT_GET(IE_SAVEDYPOS
);
3270 target
->SetOrientation(STAT_GET(IE_SAVEDFACE
), false);
3272 case 3: //owner swapped with target
3273 if (Owner
->Type
!=ST_ACTOR
) {
3274 return FX_NOT_APPLIED
;
3277 target
->SetPosition(Owner
->Pos
, true, 0);
3278 target
= (Actor
*) Owner
;
3281 target
->SetPosition(p
, true, 0 );
3282 return FX_NOT_APPLIED
;
3286 int fx_knock (Scriptable
* Owner
, Actor
* /*target*/, Effect
* fx
)
3288 if (0) printf( "fx_knock (%2d) [%d.%d]\n", fx
->Opcode
, fx
->PosX
, fx
->PosY
);
3289 Map
*map
= Owner
->GetCurrentArea();
3291 return FX_NOT_APPLIED
;
3293 Point
p(fx
->PosX
, fx
->PosY
);
3295 printf("KNOCK Pos: %d.%d\n", fx
->PosX
, fx
->PosY
);
3296 Door
*door
= map
->TMap
->GetDoorByPosition(p
);
3298 printf("Got a door\n");
3299 if (door
->LockDifficulty
<100) {
3300 door
->SetDoorLocked(false, true);
3302 return FX_NOT_APPLIED
;
3304 Container
*container
= map
->TMap
->GetContainerByPosition(p
);
3306 printf("Got a container\n");
3307 if(container
->LockDifficulty
<100) {
3308 container
->SetContainerLocked(false);
3310 return FX_NOT_APPLIED
;
3312 return FX_NOT_APPLIED
;
3315 // 0x7e MovementRateModifier
3316 // 0xb0 MovementRateModifier2
3317 int fx_movement_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3319 if (0) printf( "fx_movement_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3321 //iwd2 freeaction disables only 0xb0, who cares
3322 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
3323 //iwd2 aegis doesn't protect against grease/acid fog slowness, but that is
3325 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
3327 STAT_MOD(IE_MOVEMENTRATE
);
3332 static const ieResRef monster_summoning_2da
[FX_MS
]={"MONSUM01","MONSUM02","MONSUM03",
3333 "ANISUM01","ANISUM02", "MONSUM01", "MONSUM02","MONSUM03","ANISUM01","ANISUM02"};
3335 // 0x7f MonsterSummoning
3336 int fx_monster_summoning (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
3338 if (0) printf( "fx_monster_summoning (%2d): Number: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3339 //check the summoning limit?
3341 return FX_NOT_APPLIED
;
3344 if (!Owner
->GetCurrentArea()) {
3348 //get monster resref from 2da determined by fx->Resource or fx->Parameter2
3349 //the only addition to the original engine is that fx->Resource can be
3350 //used to specify a 2da (if parameter2 is >= 10)
3355 int level
= fx
->Parameter1
;
3357 if (fx
->Parameter2
>=FX_MS
) {
3358 if (fx
->Resource
[0]) {
3359 strnuprcpy(table
, fx
->Resource
, 8);
3361 strnuprcpy(table
, "ANISUM03", 8);
3364 strnuprcpy(table
, monster_summoning_2da
[fx
->Parameter2
], 8);
3366 core
->GetResRefFrom2DA(monster_summoning_2da
[fx
->Parameter2
], monster
, hit
, areahit
);
3369 strnuprcpy(hit
,fx
->Resource2
,8);
3372 strnuprcpy(areahit
,fx
->Resource3
,8);
3375 //the monster should appear near the effect position
3376 Point
p(fx
->PosX
, fx
->PosY
);
3378 Effect
*newfx
= EffectQueue::CreateUnsummonEffect(fx
);
3379 //The hostile flag should cover these cases, all else is arbitrary
3380 //0,1,2,3,4 - friendly to target
3381 //5,6,7,8,9 - hostile to target
3382 //10 - friendly to target
3385 if (fx
->Parameter2
>=5 && fx
->Parameter2
<=9) {
3392 //caster may be important here (Source), even if currently the EA modifiers
3394 Scriptable
*caster
= GetCaster(Owner
, fx
);
3395 core
->SummonCreature(monster
, hit
, caster
, target
, p
, eamod
, level
, newfx
);
3397 return FX_NOT_APPLIED
;
3400 // 0x80 State:Confused
3401 int fx_set_confused_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3403 if (0) printf( "fx_set_confused_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3405 if (target
->HasSpellState(SS_BLOODRAGE
)) {
3406 return FX_NOT_APPLIED
;
3409 if (fx
->TimingMode
==FX_DURATION_DELAY_PERMANENT
) {
3410 BASE_STATE_SET( STATE_CONFUSED
);
3412 STATE_SET( STATE_CONFUSED
);
3414 //NOTE: iwd2 is also unable to display the portrait icon
3415 //for permanent confusion
3416 if (enhanced_effects
) {
3417 target
->AddPortraitIcon(PI_CONFUSED
);
3419 return FX_PERMANENT
;
3422 // 0x81 AidNonCumulative
3423 int fx_set_aid_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3425 if (0) printf( "fx_set_aid_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3426 if (!fx
->Parameter2
) {
3427 fx
->Parameter2
=core
->Roll(fx
->Parameter1
,8,0);
3429 if (STATE_GET (STATE_AID
) ) //aid is non cumulative
3430 return FX_NOT_APPLIED
;
3431 STATE_SET( STATE_AID
);
3432 target
->SetSpellState(SS_AID
);
3433 STAT_ADD( IE_MAXHITPOINTS
, fx
->Parameter2
);
3434 //This better happens after increasing maxhitpoints
3435 if (fx
->FirstApply
) {
3436 BASE_ADD( IE_HITPOINTS
, fx
->Parameter1
);
3438 STAT_ADD( IE_SAVEVSDEATH
, fx
->Parameter1
);
3439 STAT_ADD( IE_SAVEVSWANDS
, fx
->Parameter1
);
3440 STAT_ADD( IE_SAVEVSPOLY
, fx
->Parameter1
);
3441 STAT_ADD( IE_SAVEVSBREATH
, fx
->Parameter1
);
3442 STAT_ADD( IE_SAVEVSSPELL
, fx
->Parameter1
);
3444 STAT_ADD( IE_TOHIT
, fx
->Parameter1
);
3445 STAT_ADD( IE_MORALEBREAK
, fx
->Parameter1
);
3446 if (enhanced_effects
) {
3447 target
->AddPortraitIcon(PI_AID
);
3448 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 50, 50, 50);
3453 // 0x82 BlessNonCumulative
3455 static EffectRef fx_bane_ref
={"Bane",NULL
,-1};
3457 int fx_set_bless_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3459 if (0) printf( "fx_set_bless_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3461 if (STATE_GET (STATE_BLESS
) ) //bless is non cumulative
3462 return FX_NOT_APPLIED
;
3465 target
->fxqueue
.RemoveAllEffects(fx_bane_ref
);
3467 STATE_SET( STATE_BLESS
);
3468 target
->SetSpellState(SS_BLESS
);
3469 STAT_ADD( IE_TOHIT
, fx
->Parameter1
);
3470 STAT_ADD( IE_MORALEBREAK
, fx
->Parameter1
);
3471 if (enhanced_effects
) {
3472 target
->AddPortraitIcon(PI_BLESS
);
3473 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0xc0, 0x80, 0);
3477 // 0x83 ChantNonCumulative
3478 int fx_set_chant_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3480 if (0) printf( "fx_set_chant_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3482 if (STATE_GET (STATE_CHANT
) ) //chant is non cumulative
3483 return FX_NOT_APPLIED
;
3484 STATE_SET( STATE_CHANT
);
3485 target
->SetSpellState(SS_GOODCHANT
);
3486 STAT_ADD( IE_LUCK
, fx
->Parameter1
);
3490 // 0x84 HolyNonCumulative
3491 int fx_set_holy_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3493 if (0) printf( "fx_set_holy_state (%2d): Modifier: %d\n", fx
->Opcode
, fx
->Parameter1
);
3495 if (STATE_GET (STATE_HOLY
) ) //holy power is non cumulative
3496 return FX_NOT_APPLIED
;
3497 STATE_SET( STATE_HOLY
);
3498 //setting the spell state to be compatible with iwd2
3499 target
->SetSpellState(SS_HOLYMIGHT
);
3500 STAT_ADD( IE_STR
, fx
->Parameter1
);
3501 STAT_ADD( IE_CON
, fx
->Parameter1
);
3502 STAT_ADD( IE_DEX
, fx
->Parameter1
);
3503 if (enhanced_effects
) {
3504 target
->AddPortraitIcon(PI_HOLY
);
3505 target
->SetColorMod(0xff, RGBModifier::ADD
, 30, 0x80, 0x80, 0x80);
3510 // 0x85 LuckNonCumulative
3511 int fx_luck_non_cumulative (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3513 if (0) printf( "fx_luck_non_cumulative (%2d): Modifier: %d\n", fx
->Opcode
, fx
->Parameter1
);
3515 if (STATE_GET (STATE_LUCK
) ) //this luck is non cumulative
3516 return FX_NOT_APPLIED
;
3517 STATE_SET( STATE_LUCK
);
3518 target
->SetSpellState(SS_LUCK
);
3519 STAT_ADD( IE_LUCK
, fx
->Parameter1
);
3520 STAT_ADD( IE_DAMAGELUCK
, fx
->Parameter1
);
3524 // 0x85 LuckCumulative (iwd2)
3525 int fx_luck_cumulative (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3527 if (0) printf( "fx_luck_cumulative (%2d): Modifier: %d\n", fx
->Opcode
, fx
->Parameter1
);
3529 target
->SetSpellState(SS_LUCK
);
3530 STAT_ADD( IE_LUCK
, fx
->Parameter1
);
3531 STAT_ADD( IE_DAMAGELUCK
, fx
->Parameter1
);
3535 // 0x86 State:Petrification
3536 int fx_set_petrified_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3538 if (0) printf( "fx_set_petrified_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3540 BASE_STATE_SET( STATE_PETRIFIED
);
3541 return FX_NOT_APPLIED
; //permanent effect
3545 static EffectRef fx_polymorph_ref
={"Polymorph",NULL
,-1};
3547 void CopyPolymorphStats(Actor
*source
, Actor
*target
)
3551 if(!polymorph_stats
) {
3552 AutoTable
tab("polystat");
3554 polymorph_stats
= (int *) malloc(0);
3558 polystatcount
= tab
->GetRowCount();
3559 polymorph_stats
=(int *) malloc(sizeof(int)*polystatcount
);
3560 for (i
=0;i
<polystatcount
;i
++) {
3561 polymorph_stats
[i
]=core
->TranslateStat(tab
->QueryField(i
,0));
3565 assert(target
->polymorphCache
);
3567 if (!target
->polymorphCache
->stats
) {
3568 target
->polymorphCache
->stats
= new ieDword
[polystatcount
];
3571 for(i
=0;i
<polystatcount
;i
++) {
3572 target
->polymorphCache
->stats
[i
] = source
->Modified
[polymorph_stats
[i
]];
3576 int fx_polymorph (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3578 if (0) printf( "fx_set_polymorph_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3580 if (!gamedata
->Exists(fx
->Resource
,IE_CRE_CLASS_ID
)) {
3581 //kill all polymorph effects
3582 target
->fxqueue
.RemoveAllEffectsWithParam(fx_polymorph_ref
, fx
->Parameter2
);
3583 //destroy the magic item slot
3584 target
->inventory
.RemoveItem(target
->inventory
.GetMagicSlot() );
3585 return FX_NOT_APPLIED
;
3588 // to avoid repeatedly loading the file or keeping all the data around
3589 // wasting memory, we keep a PolymorphCache object around, with only
3590 // the data we need from the polymorphed creature
3592 if (!target
->polymorphCache
) {
3594 target
->polymorphCache
= new PolymorphCache();
3596 if (!cached
|| strnicmp(fx
->Resource
,target
->polymorphCache
->Resource
,sizeof(fx
->Resource
))) {
3597 Actor
*newCreature
= gamedata
->GetCreature(fx
->Resource
,0);
3599 //I don't know how could this happen, existance of the resource was already checked
3601 return FX_NOT_APPLIED
;
3604 memcpy(target
->polymorphCache
->Resource
, fx
->Resource
, sizeof(fx
->Resource
));
3605 CopyPolymorphStats(newCreature
, target
);
3610 //copy all polymorphed stats
3611 if(!fx
->Parameter2
) {
3612 STAT_SET( IE_POLYMORPHED
, 1 );
3613 //disable mage and cleric spells (see IE_CASTING doc above)
3614 STAT_BIT_OR(IE_CASTING
, 6);
3615 STAT_BIT_OR(IE_DISABLEDBUTTON
, (1<<ACT_CAST
)|(1<<ACT_QSPELL1
)|(1<<ACT_QSPELL2
)|(1<<ACT_QSPELL3
) );
3618 for(int i
=0;i
<polystatcount
;i
++) {
3619 //copy only the animation ID
3620 if (fx
->Parameter2
&& polymorph_stats
[i
] != IE_ANIMATION_ID
) continue;
3622 target
->SetStat(polymorph_stats
[i
], target
->polymorphCache
->stats
[i
], 1);
3628 // 0x88 ForceVisible
3629 int fx_force_visible (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3631 if (0) printf( "fx_force_visible (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3634 BASE_STATE_CURE(STATE_PST_INVIS
);
3636 BASE_STATE_CURE(STATE_INVISIBLE
);
3638 target
->fxqueue
.RemoveAllEffectsWithParam(fx_set_invisible_state_ref
,0);
3639 target
->fxqueue
.RemoveAllEffectsWithParam(fx_set_invisible_state_ref
,2);
3640 return FX_NOT_APPLIED
;
3643 // 0x89 ChantBadNonCumulative
3644 int fx_set_chantbad_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3646 if (0) printf( "fx_set_chantbad_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3648 if (STATE_GET (STATE_CHANTBAD
) ) //chant is non cumulative
3649 return FX_NOT_APPLIED
;
3650 STATE_SET( STATE_CHANTBAD
);
3651 target
->SetSpellState(SS_BADCHANT
);
3652 STAT_SUB( IE_LUCK
, fx
->Parameter1
);
3656 // 0x8A AnimationStateChange
3657 int fx_animation_stance (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3659 if (0) printf( "fx_animation_stance (%2d): Stance: %d\n", fx
->Opcode
, fx
->Parameter2
);
3661 //this effect works only on living actors
3662 if ( !STATE_GET(STATE_DEAD
) ) {
3663 target
->SetStance(fx
->Parameter2
);
3665 return FX_NOT_APPLIED
;
3668 // 0x8B DisplayString
3669 // gemrb extension: rgb colour for displaystring
3670 static EffectRef fx_protection_from_display_string_ref
={"Protection:String",NULL
,-1};
3672 int fx_display_string (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3674 if (0) printf( "fx_display_string (%2d): StrRef: %d\n", fx
->Opcode
, fx
->Parameter1
);
3675 if (!target
->fxqueue
.HasEffectWithParamPair(fx_protection_from_display_string_ref
, fx
->Parameter1
, 0) ) {
3676 displaymsg
->DisplayStringName(fx
->Parameter1
, fx
->Parameter2
?fx
->Parameter2
:0xffffff, target
, IE_STR_SOUND
|IE_STR_SPEECH
);
3678 return FX_NOT_APPLIED
;
3682 static const int ypos_by_direction
[16]={10,10,10,0,-10,-10,-10,-10,-10,-10,-10,-10,0,10,10,10};
3683 static const int xpos_by_direction
[16]={0,-10,-12,-14,-16,-14,-12,-10,0,10,12,14,16,14,12,10};
3685 int fx_casting_glow (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3687 if (0) printf( "fx_casting_glow (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
3689 cgcount
= core
->ReadResRefTable("cgtable",casting_glows
);
3691 //remove effect if map is not loaded
3692 Map
*map
= target
->GetCurrentArea();
3694 return FX_NOT_APPLIED
;
3697 if (fx
->Parameter2
<(ieDword
) cgcount
) {
3698 ScriptedAnimation
*sca
= gamedata
->GetScriptedAnimation(casting_glows
[fx
->Parameter2
], false);
3699 //remove effect if animation doesn't exist
3701 return FX_NOT_APPLIED
;
3703 //12 is just an approximate value to set the height of the casting glow
3704 //based on the avatar's size
3705 int heightmod
= target
->GetAnims()->GetCircleSize()*12;
3706 sca
->XPos
+=fx
->PosX
+xpos_by_direction
[target
->GetOrientation()];
3707 sca
->YPos
+=fx
->PosY
+ypos_by_direction
[target
->GetOrientation()];
3708 sca
->ZPos
+=heightmod
;
3711 sca
->SetDefaultDuration(fx
->Duration
-core
->GetGame()->GameTime
);
3713 sca
->SetDefaultDuration(10000);
3715 map
->AddVVCell(sca
);
3717 return FX_NOT_APPLIED
;
3720 //0x8d VisualSpellHit
3721 int fx_visual_spell_hit (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3723 if (0) printf( "fx_visual_spell_hit (%2d): Target: %d Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
3725 shcount
= core
->ReadResRefTable("shtable",spell_hits
);
3727 //remove effect if map is not loaded
3728 Map
*map
= target
->GetCurrentArea();
3730 return FX_NOT_APPLIED
;
3732 if (fx
->Parameter2
<(ieDword
) shcount
) {
3733 ScriptedAnimation
*sca
= gamedata
->GetScriptedAnimation(spell_hits
[fx
->Parameter2
], false);
3734 //remove effect if animation doesn't exist
3736 return FX_NOT_APPLIED
;
3738 if (fx
->Parameter1
) {
3739 sca
->XPos
+=target
->Pos
.x
;
3740 sca
->YPos
+=target
->Pos
.y
;
3742 sca
->XPos
+=fx
->PosX
;
3743 sca
->YPos
+=fx
->PosY
;
3745 if (fx
->Parameter2
<32) {
3746 int tmp
= fx
->Parameter2
>>2;
3748 sca
->SetFullPalette(tmp
);
3753 map
->AddVVCell(sca
);
3755 printf("fx_visual_spell_hit: Unhandled Type: %d\n", fx
->Parameter2
);
3757 return FX_NOT_APPLIED
;
3761 int fx_display_portrait_icon (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3763 if (0) printf( "fx_display_string (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
3764 target
->AddPortraitIcon(fx
->Parameter2
);
3768 //0x8f Item:CreateInSlot
3769 int fx_create_item_in_slot (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3771 if (0) printf( "fx_create_item_in_slot (%2d): Button: %d\n", fx
->Opcode
, fx
->Parameter2
);
3772 //create item and set it in target's slot
3773 target
->inventory
.SetSlotItemRes( fx
->Resource
, core
->QuerySlot(fx
->Parameter2
), fx
->Parameter1
, fx
->Parameter3
, fx
->Parameter4
);
3774 if ((fx
->TimingMode
&0xff) == FX_DURATION_INSTANT_LIMITED
) {
3775 //convert it to a destroy item
3776 fx
->Opcode
=EffectQueue::ResolveEffect(fx_remove_item_ref
);
3777 fx
->TimingMode
=FX_DURATION_DELAY_PERMANENT
;
3780 return FX_NOT_APPLIED
;
3783 // 0x90 DisableButton
3784 // different in iwd2 and the rest (maybe also in how: 0-7?)
3785 int fx_disable_button (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3787 if (0) printf( "fx_disable_button (%2d): Button: %d\n", fx
->Opcode
, fx
->Parameter2
);
3789 // iwd2 has a flexible action bar, so there are more possible parameter values
3790 // only values 0-5 match the bg2 constants (which map to ACT_*)
3791 // FIXME: support disabling all iwd2 buttons
3792 if (target
->spellbook
.IsIWDSpellBook()) {
3793 if (fx
->Parameter2
< 6) STAT_BIT_OR( IE_DISABLEDBUTTON
, 1<<fx
->Parameter2
);
3795 STAT_BIT_OR( IE_DISABLEDBUTTON
, 1<<fx
->Parameter2
);
3798 if (fx
->FirstApply
&& target
->GetStat(IE_EA
) < EA_CONTROLLABLE
) {
3799 core
->SetEventFlag(EF_ACTION
);
3804 //0x91 DisableSpellCasting
3805 //bg2: (-1 item), 0 - mage, 1 - cleric, 2 - innate, 3 - class
3806 //iwd2: (-1 item), 0 - all, 1 - mage+cleric, 2 - mage, 3 - cleric , 4 - innate,( 5 - class)
3808 /*internal representation of disabled spells in IE_CASTING (bitfield):
3816 static ieDword dsc_bits_iwd2
[7]={1, 14, 6, 2, 4, 8, 16};
3817 static ieDword dsc_bits_bg2
[7]={1, 4, 2, 8, 16, 14, 6};
3818 int fx_disable_spellcasting (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3820 if (0) printf( "fx_disable_spellcasting (%2d): Button: %d\n", fx
->Opcode
, fx
->Parameter2
);
3822 bool display_warning
= false;
3823 ieDword tmp
= fx
->Parameter2
+1;
3825 //IWD2 Style spellbook
3826 if (target
->spellbook
.IsIWDSpellBook()) {
3827 switch(fx
->Parameter2
) {
3829 case 1: // mage and cleric
3831 if (target
->spellbook
.GetKnownSpellsCount(IE_IWD2_SPELL_BARD
, 0)) display_warning
= true;
3832 if (target
->spellbook
.GetKnownSpellsCount(IE_IWD2_SPELL_SORCEROR
, 0)) display_warning
= true;
3833 if (target
->spellbook
.GetKnownSpellsCount(IE_IWD2_SPELL_WIZARD
, 0)) display_warning
= true;
3837 STAT_BIT_OR(IE_CASTING
, dsc_bits_iwd2
[tmp
] );
3840 if (fx
->Parameter2
== 0) {
3841 if (target
->spellbook
.GetKnownSpellsCount(IE_SPELL_TYPE_WIZARD
, 0)) display_warning
= true;
3849 STAT_BIT_OR(IE_CASTING
, dsc_bits_bg2
[tmp
] );
3852 if (fx
->FirstApply
&& display_warning
&& target
->GetStat(IE_EA
) < EA_CONTROLLABLE
) {
3853 displaymsg
->DisplayConstantStringName(STR_DISABLEDMAGE
, 0xff0000, target
);
3854 core
->SetEventFlag(EF_ACTION
);
3860 int fx_cast_spell (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
3862 if (0) printf( "fx_cast_spell (%2d): Resource:%s Mode: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
3863 if (fx
->Parameter2
) {
3864 //apply spell on target
3865 core
->ApplySpell(fx
->Resource
, target
, Owner
, fx
->Power
);
3867 // give feedback: Caster - spellname : target
3869 Spell
*spl
= gamedata
->GetSpell(fx
->Resource
);
3871 snprintf(tmp
, sizeof(tmp
), "%s : %s", core
->GetString(spl
->SpellName
), target
->GetName(-1));
3872 displaymsg
->DisplayStringName(tmp
, 0xffffff, Owner
);
3875 //cast spell on target
3876 Owner
->CastSpell(fx
->Resource
, target
, false);
3877 //actually finish casting (if this is not good enough, use an action???)
3878 Owner
->CastSpellEnd(fx
->Resource
);
3880 return FX_NOT_APPLIED
;
3884 int fx_learn_spell (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3886 if (0) printf( "fx_learn_spell (%2d): Resource:%s Mode: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
3887 //parameter1 is unused, gemrb lets you to make it not give XP
3888 //probably we should also let this via a game flag if we want
3889 //full compatibility with bg1
3890 target
->LearnSpell(fx
->Resource
, fx
->Parameter2
^LS_ADDXP
);
3891 return FX_NOT_APPLIED
;
3893 // 0x94 Spell:CastSpellPoint
3894 int fx_cast_spell_point (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
3896 if (0) printf( "fx_cast_spell_point (%2d): Resource:%s Mode: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
3897 Owner
->CastSpellPoint(fx
->Resource
, target
->Pos
, false);
3898 //actually finish casting (if this is not good enough, use an action???)
3899 Owner
->CastSpellPointEnd(fx
->Resource
);
3900 return FX_NOT_APPLIED
;
3904 int fx_identify (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3906 if (0) printf( "fx_identify (%2d): Resource:%s Mode: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
3907 if (target
->InParty
) {
3908 BASE_SET (IE_IDENTIFYMODE
, 1);
3909 core
->SetEventFlag(EF_IDENTIFY
);
3911 return FX_NOT_APPLIED
;
3914 // (actually, in bg2 the effect targets area objects and the range is implemented
3915 // by the inareans projectile) - inanimate, area, no sprite
3916 // TODO: effects should target inanimates using different code
3917 // 0 - detect traps automatically
3918 // 1 - detect traps by skill
3919 // 2 - detect secret doors automatically
3920 // 3 - detect secret doors by luck
3921 int fx_find_traps (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
3923 if (0) printf( "fx_find_traps (%2d)\n", fx
->Opcode
);
3924 //reveal trapped containers, doors, triggers that are in the visible range
3925 ieDword range
= target
->GetStat(IE_VISUALRANGE
)*10;
3927 bool detecttraps
= true;
3929 switch(fx
->Parameter2
) {
3931 skill
= target
->GetStat(IE_TRAPS
);
3934 //detect secret doors
3935 skill
= target
->LuckyRoll(1,100,0);
3936 detecttraps
= false;
3939 detecttraps
= false;
3941 //automatic find traps
3946 TileMap
*TMap
= target
->GetCurrentArea()->TMap
;
3950 Door
* door
= TMap
->GetDoor( Count
++ );
3953 if (Distance(door
->Pos
, target
->Pos
)<range
) {
3955 //when was door trap noticed
3956 door
->DetectTrap(skill
);
3958 door
->TryDetectSecret(skill
);
3963 return FX_NOT_APPLIED
;
3968 Container
* container
= TMap
->GetContainer( Count
++ );
3971 if (Distance(container
->Pos
, target
->Pos
)<range
) {
3972 //when was door trap noticed
3973 container
->DetectTrap(skill
);
3980 InfoPoint
* trap
= TMap
->GetInfoPoint( Count
++ );
3983 if (Distance(trap
->Pos
, target
->Pos
)<range
) {
3984 //when was door trap noticed
3985 trap
->DetectTrap(skill
);
3989 return FX_NOT_APPLIED
;
3992 // 0x97 ReplaceCreature
3993 int fx_replace_creature (Scriptable
* Owner
, Actor
* target
, Effect
*fx
)
3995 if (0) printf( "fx_replace_creature (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
3997 //this safeguard exists in the original engine too
3998 if (!gamedata
->Exists(fx
->Resource
,IE_CRE_CLASS_ID
)) {
3999 return FX_NOT_APPLIED
;
4002 //the monster should appear near the effect position? (unsure)
4003 Point
p(fx
->PosX
, fx
->PosY
);
4005 //remove old creature
4006 switch(fx
->Parameter2
) {
4007 case 0: //remove silently
4008 target
->DestroySelf();
4010 case 1: //chunky death
4011 target
->NewBase(IE_HITPOINTS
,(ieDword
) -100, MOD_ABSOLUTE
);
4014 case 2: //normal death
4019 //create replacement; should we be passing the target instead of NULL?
4020 //noooo, don't unsummon replacement creatures! - fuzzie
4021 //Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
4022 core
->SummonCreature(fx
->Resource
, fx
->Resource2
, Owner
, NULL
,p
, EAM_DEFAULT
,-1, NULL
, 0);
4024 return FX_NOT_APPLIED
;
4028 int fx_play_movie (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
4030 if (0) printf( "fx_play_movie (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
4031 core
->PlayMovie (fx
->Resource
);
4032 return FX_NOT_APPLIED
;
4034 // 0x99 Overlay:Sanctuary
4035 #define ICE_GRADIENT 71
4037 static const ieDword fullwhite
[7]={ICE_GRADIENT
,ICE_GRADIENT
,ICE_GRADIENT
,ICE_GRADIENT
,ICE_GRADIENT
,ICE_GRADIENT
,ICE_GRADIENT
};
4039 int fx_set_sanctuary_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4041 //iwd and bg are a bit different, but we solve the whole stuff in a single opcode
4042 if (0) printf( "fx_set_sanctuary_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4043 if (target
->HasSpellState(SS_SANCTUARY
)) return FX_NOT_APPLIED
;
4044 if (!fx
->Parameter2
) {
4047 //this effect needs the pcf run immediately
4048 STAT_SET_PCF( IE_SANCTUARY
, fx
->Parameter2
);
4049 //a rare event, but this effect gives more in bg2 than in iwd2
4050 //so we use this flag
4051 if (!enhanced_effects
)
4053 target
->SetLockedPalette(fullwhite
);
4058 // 0x9a Overlay:Entangle
4059 int fx_set_entangle_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4061 if (0) printf( "fx_set_entangle_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4063 //iwd2 effects that disable entangle
4064 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
4065 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
4067 if (!fx
->Parameter2
) {
4070 STAT_SET_PCF( IE_ENTANGLE
, fx
->Parameter2
);
4074 // 0x9b Overlay:MinorGlobe
4075 int fx_set_minorglobe_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4077 if (0) printf( "fx_set_minorglobe_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4078 //the resisted levels are stored in minor globe (bit 2-)
4079 //the globe effect is stored in the first bit
4080 STAT_BIT_OR_PCF( IE_MINORGLOBE
, 1);
4084 // 0x9c Overlay:ShieldGlobe
4085 int fx_set_shieldglobe_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4087 if (0) printf( "fx_set_shieldglobe_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4088 //the shield vanishes on dead
4089 if (STATE_GET(STATE_DEAD
) ) {
4090 return FX_NOT_APPLIED
;
4092 STAT_SET_PCF( IE_SHIELDGLOBE
, 1);
4097 int fx_set_web_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4099 if (0) printf( "fx_set_web_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4101 //iwd2 effects that disable web
4102 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
4103 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
4105 target
->SetSpellState(SS_WEB
);
4106 //attack penalty in IWD2
4107 STAT_SET_PCF( IE_WEB
, 1);
4108 STAT_SET(IE_MOVEMENTRATE
, 0); //
4112 // 0x9e Overlay:Grease
4113 int fx_set_grease_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4115 if (0) printf( "fx_set_grease_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4117 //iwd2 effects that disable grease
4118 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
4119 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
4121 target
->SetSpellState(SS_GREASE
);
4122 STAT_SET_PCF( IE_GREASE
, 1);
4123 //the movement rate is set by separate opcodes in all engines
4127 // 0x9f MirrorImageModifier
4128 int fx_mirror_image_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4130 if (0) printf( "fx_mirror_image_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter1
);
4131 if (STATE_GET(STATE_DEAD
) ) {
4132 return FX_NOT_APPLIED
;
4134 if (!fx
->Parameter1
) {
4135 return FX_NOT_APPLIED
;
4138 STATE_SET( STATE_PST_MIRROR
);
4141 STATE_SET( STATE_MIRROR
);
4143 if (fx
->Parameter2
) {
4144 target
->SetSpellState(SS_REFLECTION
);
4146 target
->SetSpellState(SS_MIRRORIMAGE
);
4148 //actually, there is no such stat in the original IE
4149 STAT_SET( IE_MIRRORIMAGES
, fx
->Parameter1
);
4153 // 0xa0 Cure:Sanctuary
4154 static EffectRef fx_sanctuary_state_ref
={"Overlay:Sanctuary",NULL
,-1};
4156 int fx_cure_sanctuary_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4158 if (0) printf( "fx_cure_sanctuary_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4159 STAT_SET( IE_SANCTUARY
, 0);
4160 target
->fxqueue
.RemoveAllEffects(fx_sanctuary_state_ref
);
4161 return FX_NOT_APPLIED
;
4165 static EffectRef fx_set_panic_state_ref
={"State:Panic",NULL
,-1};
4167 int fx_cure_panic_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4169 if (0) printf( "fx_cure_panic_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4170 BASE_STATE_CURE( STATE_PANIC
);
4171 target
->fxqueue
.RemoveAllEffects(fx_set_panic_state_ref
);
4172 return FX_NOT_APPLIED
;
4176 static EffectRef fx_hold_creature_ref
={"State:Hold",NULL
,-1};
4178 int fx_cure_hold_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4180 if (0) printf( "fx_cure_hold_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4181 //note that this effect doesn't remove 185 (another hold effect)
4182 target
->fxqueue
.RemoveAllEffects( fx_hold_creature_ref
);
4183 target
->fxqueue
.RemoveAllEffects(fx_hold_creature_no_icon_ref
);
4184 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_HELD
);
4185 return FX_NOT_APPLIED
;
4189 static EffectRef fx_movement_modifier_ref
={"MovementRateModifier2",NULL
,-1};
4191 int fx_cure_slow_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4193 if (0) printf( "fx_cure_slow_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4194 target
->fxqueue
.RemoveAllEffects( fx_movement_modifier_ref
);
4195 // STATE_CURE( STATE_SLOWED );
4196 return FX_NOT_APPLIED
;
4199 // 0xa4 Cure:Intoxication
4200 static EffectRef fx_intoxication_ref
={"IntoxicationModifier",NULL
,-1};
4202 int fx_cure_intoxication (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4204 if (0) printf( "fx_cure_intoxication (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4205 target
->fxqueue
.RemoveAllEffects( fx_intoxication_ref
);
4206 BASE_SET(IE_INTOXICATION
,0);
4207 return FX_NOT_APPLIED
;
4211 int fx_pause_target (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4213 if (0) printf( "fx_pause_target (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4215 STAT_MOD( IE_CASTERHOLD
);
4216 return FX_PERMANENT
;
4219 // 0xa6 MagicResistanceModifier
4220 int fx_magic_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4222 if (0) printf( "fx_magic_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4224 STAT_MOD( IE_RESISTMAGIC
);
4228 // 0xa7 MissileHitModifier
4229 int fx_missile_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4231 if (0) printf( "fx_missile_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4233 STAT_MOD( IE_MISSILEHITBONUS
);
4237 // 0xa8 RemoveCreature
4238 // removes targeted creature
4239 // removes creature specified by resource key (gemrb extension)
4240 int fx_remove_creature (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4242 if (0) printf( "fx_remove_creature (%2d)\n", fx
->Opcode
);
4243 Map
*map
= target
->GetCurrentArea();
4244 Actor
*actor
= target
;
4246 if (fx
->Resource
[0]) {
4247 actor
= map
->GetActorByResource(fx
->Resource
);
4251 //leaveparty will be handled automagically
4252 //plot critical items are not handled, shall we?
4253 actor
->DestroySelf();
4255 return FX_NOT_APPLIED
;
4258 // 0xa9 Icon:Disable
4259 int fx_disable_portrait_icon (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4261 if (0) printf( "fx_disable_portrait_icon (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4262 target
->DisablePortraitIcon(fx
->Parameter2
);
4266 // 0xaa DamageAnimation
4267 int fx_damage_animation (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4269 if (0) printf( "fx_damage_animation (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4271 //Parameter1 is a gemrb extension
4272 target
->PlayDamageAnimation(fx
->Parameter2
, !fx
->Parameter1
);
4273 return FX_NOT_APPLIED
;
4277 int fx_add_innate (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4279 if (0) printf( "fx_add_innate (%2d): Resource: %s Mode: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
4280 target
->LearnSpell(fx
->Resource
, fx
->Parameter2
^LS_MEMO
);
4281 //this is an instant, so it shouldn't stick
4282 return FX_NOT_APPLIED
;
4285 // 0xac Spell:Remove
4286 //gemrb extension: deplete spell by resref
4287 int fx_remove_spell (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4289 if (0) printf( "fx_remove_spell (%2d): Resource: %s Type:%d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
4290 switch (fx
->Parameter2
) {
4292 target
->spellbook
.RemoveSpell(fx
->Resource
);
4294 case 1: //forget all spells of Resource
4295 do {} while(target
->spellbook
.HaveSpell( fx
->Resource
, HS_DEPLETE
));
4297 case 2: //forget x spells of resource
4298 while( fx
->Parameter1
--) {
4299 target
->spellbook
.HaveSpell( fx
->Resource
, HS_DEPLETE
);
4303 //this is an instant, so it shouldn't stick
4304 return FX_NOT_APPLIED
;
4307 // 0xad PoisonResistanceModifier
4308 int fx_poison_resistance_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4310 if (0) printf( "fx_poison_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4312 STAT_MOD( IE_RESISTPOISON
);
4317 int fx_playsound (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4319 if (0) printf( "fx_playsound (%s)", fx
->Resource
);
4320 //this is probably inaccurate
4322 core
->GetAudioDrv()->Play(fx
->Resource
, target
->Pos
.x
, target
->Pos
.y
);
4324 core
->GetAudioDrv()->Play(fx
->Resource
);
4326 //this is an instant, it shouldn't stick
4327 return FX_NOT_APPLIED
;
4332 int fx_hold_creature_no_icon (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4334 if (0) printf( "fx_hold_creature_no_icon (%2d): Value: %d, IDS: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4336 //actually the original engine just skips this effect if the target is dead
4337 if ( STATE_GET(STATE_DEAD
) ) {
4338 return FX_NOT_APPLIED
;
4341 if (!EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
4342 //if the ids don't match, the effect doesn't stick
4343 return FX_NOT_APPLIED
;
4345 target
->SetSpellState(SS_HELD
);
4346 STAT_SET( IE_HELD
, 1);
4352 //(0x6d/0x1a8 for iwd2)
4353 int fx_hold_creature (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4355 if (0) printf( "fx_hold_creature (%2d): Value: %d, IDS: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4357 //actually the original engine just skips this effect if the target is dead
4358 if ( STATE_GET(STATE_DEAD
) ) {
4359 return FX_NOT_APPLIED
;
4362 //iwd2 free action or blood rage disables this effect
4363 if (target
->HasSpellState(SS_FREEACTION
)) return FX_NOT_APPLIED
;
4364 if (target
->HasSpellState(SS_BLOODRAGE
)) return FX_NOT_APPLIED
;
4365 if (target
->HasSpellState(SS_AEGIS
)) return FX_NOT_APPLIED
;
4367 if (!EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
4368 //if the ids don't match, the effect doesn't stick
4369 return FX_NOT_APPLIED
;
4371 target
->SetSpellState(SS_HELD
);
4372 STAT_SET( IE_HELD
, 1);
4373 target
->AddPortraitIcon(PI_HELD
);
4376 //0xb0 see: fx_movement_modifier
4379 int fx_apply_effect (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4381 if (0) printf( "fx_apply_effect (%2d) %s", fx
->Opcode
, fx
->Resource
);
4383 //this effect executes a file effect in place of this effect
4384 //the file effect inherits the target and the timingmode, but gets
4385 //a new chance to roll percents
4386 int ret
= FX_NOT_APPLIED
;
4390 if (EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
4391 Point
p(fx
->PosX
, fx
->PosY
);
4393 //apply effect, if the effect is a goner, then kill
4395 Effect
*newfx
= core
->GetEffect(fx
->Resource
, fx
->Power
, p
);
4397 Effect
*myfx
= new Effect
;
4398 memcpy(myfx
, newfx
, sizeof(Effect
));
4399 myfx
->random_value
= core
->Roll(1,100,-1);
4400 myfx
->Target
= FX_TARGET_PRESET
;
4401 myfx
->TimingMode
= fx
->TimingMode
;
4402 myfx
->Duration
= fx
->Duration
;
4403 myfx
->CasterID
= fx
->CasterID
;
4404 ret
= target
->fxqueue
.ApplyEffect(target
, myfx
, fx
->FirstApply
, !fx
->Parameter3
);
4408 //newfx is a borrowed reference don't delete it
4413 //0xb2 hitbonus generic effect ToHitVsCreature
4414 //0xb3 damagebonus generic effect DamageVsCreature
4415 // b4 can't use item (resource) generic effect CantUseItem
4416 // b5 can't use itemtype (resource) generic effect CantUseItemType
4418 // b6 generic effect ApplyEffectItem
4419 int fx_apply_effect_item (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4421 if (0) printf("fx_apply_effect_item (%2d) (%.8s)\n", fx
->Opcode
, fx
->Resource
);
4422 if (target
->inventory
.HasItem(fx
->Resource
, 0) ) {
4423 core
->ApplySpell(fx
->Resource2
, target
, Owner
, fx
->Parameter1
);
4424 return FX_NOT_APPLIED
;
4429 // b7 generic effect ApplyEffectItemType
4430 int fx_apply_effect_item_type (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4432 if (0) printf("fx_apply_effect_item (%2d), Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4433 if (target
->inventory
.HasItemType(fx
->Parameter2
) ) {
4434 core
->ApplySpell(fx
->Resource
, target
, Owner
, fx
->Parameter1
);
4435 return FX_NOT_APPLIED
;
4440 // b8 DontJumpModifier
4441 int fx_dontjump_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4443 if (0) printf( "fx_dontjump_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4444 STAT_SET( IE_DONOTJUMP
, fx
->Parameter2
);
4448 //0xb9 see above: fx_hold_creature
4451 int fx_move_to_area (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4453 if (0) printf( "fx_move_to_area (%2d) %s", fx
->Opcode
, fx
->Resource
);
4454 //delay effect until the target has finished the previous move to an area
4455 //hopefully this fixes an evil bug
4456 Map
*map
= target
->GetCurrentArea();
4457 if (!map
|| !map
->HasActor(target
)) {
4458 //stay around for the next evaluation
4461 Point
p(fx
->PosX
,fx
->PosY
);
4462 MoveBetweenAreasCore(target
, fx
->Resource
, p
, fx
->Parameter2
, true);
4463 //this effect doesn't stick
4464 return FX_NOT_APPLIED
;
4467 // 0xbb Variable:StoreLocalVariable
4468 int fx_local_variable (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4470 //this is a hack, the variable name spreads across the resources
4471 if (0) printf( "fx_local_variable (%2d) %s=%d", fx
->Opcode
, fx
->Resource
, fx
->Parameter1
);
4472 target
->locals
->SetAt(fx
->Resource
, fx
->Parameter1
);
4473 //local variable effects are not applied, they will be resaved though
4474 return FX_NOT_APPLIED
;
4477 // 0xbc AuraCleansingModifier
4478 int fx_auracleansing_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4480 if (0) printf( "fx_auracleansing_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4481 STAT_SET( IE_AURACLEANSING
, fx
->Parameter2
);
4485 // 0xbd CastingSpeedModifier
4486 int fx_castingspeed_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4488 if (0) printf( "fx_castingspeed_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4489 STAT_MOD( IE_MENTALSPEED
);
4493 // 0xbe PhysicalSpeedModifier
4494 int fx_attackspeed_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4496 if (0) printf( "fx_attackspeed_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4497 STAT_MOD( IE_PHYSICALSPEED
);
4501 // 0xbf CastingLevelModifier
4502 int fx_castinglevel_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4504 if (0) printf( "fx_castinglevel_modifier (%2d) Value:%d Type:%d", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4505 switch (fx
->Parameter2
) {
4507 STAT_SET( IE_CASTINGLEVELBONUSMAGE
, fx
->Parameter1
);
4510 STAT_SET( IE_CASTINGLEVELBONUSCLERIC
, fx
->Parameter1
);
4513 return FX_NOT_APPLIED
;
4518 // 0xc0 FindFamiliar
4519 // param2 = 1 alignment is in param1
4520 // param2 = 2 resource used
4521 #define FAMILIAR_NORMAL 0
4522 #define FAMILIAR_ALIGNMENT 1
4523 #define FAMILIAR_RESOURCE 2
4525 static EffectRef fx_familiar_constitution_loss_ref
={"FamiliarBond",NULL
,-1};
4526 static EffectRef fx_familiar_marker_ref
={"FamiliarMarker",NULL
,-1};
4527 static EffectRef fx_maximum_hp_modifier_ref
={"MaximumHPModifier",NULL
,-1};
4529 int fx_find_familiar (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4531 if (0) printf( "fx_find_familiar (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4534 return FX_NOT_APPLIED
;
4537 if (!target
->GetCurrentArea()) {
4541 if (fx
->Parameter2
!=FAMILIAR_RESOURCE
) {
4544 if (fx
->Parameter2
==FAMILIAR_ALIGNMENT
) {
4545 alignment
= fx
->Parameter1
;
4547 alignment
= target
->GetStat(IE_ALIGNMENT
);
4548 alignment
= ((alignment
&AL_LC_MASK
)>>4)*3+(alignment
&AL_GE_MASK
)-4;
4551 return FX_NOT_APPLIED
;
4553 memcpy(fx
->Resource
, core
->GetGame()->Familiars
[alignment
],sizeof(ieResRef
) );
4554 fx
->Parameter2
=FAMILIAR_RESOURCE
;
4557 //summon familiar with fx->Resource
4558 Actor
*fam
= gamedata
->GetCreature(fx
->Resource
);
4560 return FX_NOT_APPLIED
;
4562 fam
->SetBase(IE_EA
, EA_FAMILIAR
);
4563 fam
->LastSummoner
= Owner
->GetGlobalID();
4565 Map
*map
= target
->GetCurrentArea();
4567 Point
p(fx
->PosX
, fx
->PosY
);
4568 fam
->SetPosition(p
, true, 0);
4569 fam
->RefreshEffects(NULL
);
4571 if (fx
->Resource2
[0]) {
4572 ScriptedAnimation
* vvc
= gamedata
->GetScriptedAnimation(fx
->Resource2
, false);
4574 //This is the final position of the summoned creature
4575 //not the original target point
4576 vvc
->XPos
=fam
->Pos
.x
;
4577 vvc
->YPos
=fam
->Pos
.y
;
4578 //force vvc to play only once
4580 map
->AddVVCell( vvc
);
4584 //Make the familiar an NPC (MoveGlobal needs this)
4585 core
->GetGame()->AddNPC(fam
);
4587 //Add some essential effects
4588 Effect
*newfx
= EffectQueue::CreateEffect(fx_familiar_constitution_loss_ref
, fam
->GetBase(IE_HITPOINTS
)/2, 0, FX_DURATION_INSTANT_PERMANENT
);
4589 core
->ApplyEffect(newfx
, fam
, fam
);
4592 newfx
= EffectQueue::CreateEffect(fx_familiar_marker_ref
, 0, 0, FX_DURATION_INSTANT_PERMANENT
);
4593 core
->ApplyEffect(newfx
, fam
, fam
);
4596 //maximum hp bonus of half the familiar's hp
4597 newfx
= EffectQueue::CreateEffect(fx_maximum_hp_modifier_ref
, fam
->GetBase(IE_HITPOINTS
)/2, MOD_ADDITIVE
, FX_DURATION_INSTANT_PERMANENT
);
4598 core
->ApplyEffect(newfx
, (Actor
*) Owner
, Owner
);
4601 return FX_NOT_APPLIED
;
4604 // 0xc1 InvisibleDetection
4605 int fx_see_invisible_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4607 if (0) printf( "fx_see_invisible_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4608 STAT_SET( IE_SEEINVISIBLE
, fx
->Parameter2
);
4612 // 0xc2 IgnoreDialogPause
4613 int fx_ignore_dialogpause_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4615 if (0) printf( "fx_ignore_dialogpause_modifier (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4616 STAT_SET( IE_IGNOREDIALOGPAUSE
, fx
->Parameter2
);
4621 //when this effect's target dies it should incur damage on protagonist
4622 static EffectRef fx_damage_opcode_ref
={"Damage",NULL
,-1};
4623 static EffectRef fx_constitution_modifier_ref
={"ConstitutionModifier",NULL
,-1};
4625 int fx_familiar_constitution_loss (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4627 if (0) printf( "fx_familiar_constitution_loss (%2d): Loss: %d\n", fx
->Opcode
,(signed) fx
->Parameter1
);
4628 if (! (STAT_GET(IE_STATE_ID
)&STATE_NOSAVE
)) {
4633 Actor
*master
= core
->GetGame()->FindPC(1);
4634 if (!master
) return FX_NOT_APPLIED
;
4636 //lose 1 point of constitution
4637 newfx
= EffectQueue::CreateEffect(fx_constitution_modifier_ref
, (ieDword
) -1, MOD_ADDITIVE
, FX_DURATION_INSTANT_PERMANENT
);
4638 core
->ApplyEffect(newfx
, master
, master
);
4641 //remove the maximum hp bonus
4642 newfx
= EffectQueue::CreateEffect(fx_maximum_hp_modifier_ref
, (ieDword
) -fx
->Parameter1
, 3, FX_DURATION_INSTANT_PERMANENT
);
4643 core
->ApplyEffect(newfx
, master
, master
);
4646 //damage for half of the familiar's hitpoints
4647 newfx
= EffectQueue::CreateEffect(fx_damage_opcode_ref
, fx
->Parameter1
, DAMAGE_CRUSHING
, FX_DURATION_INSTANT_PERMANENT
);
4648 core
->ApplyEffect(newfx
, master
, master
);
4651 return FX_NOT_APPLIED
;
4654 //0xc4 FamiliarMarker
4655 int fx_familiar_marker (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4657 if (0) printf( "fx_familiar_marker (%2d)\n", fx
->Opcode
);
4658 if (! (STAT_GET(IE_STATE_ID
)&STATE_NOSAVE
)) {
4659 //TODO: where to disable familiar?
4660 //core->GetGame()->WeatherBits|=1;
4663 //TODO: enable familiar?
4664 //core->GetGame()->WeatherBits&=~1;
4665 return FX_NOT_APPLIED
;
4668 // 0xc5 Bounce:Projectile
4669 int fx_bounce_projectile (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4671 if (0) printf( "fx_bounce_projectile (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4672 STAT_BIT_OR( IE_BOUNCE
, BNC_PROJECTILE
);
4676 // 0xc6 Bounce:Opcode
4677 int fx_bounce_opcode (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4679 if (0) printf( "fx_bounce_opcode (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4680 STAT_BIT_OR( IE_BOUNCE
, BNC_OPCODE
);
4681 target
->AddPortraitIcon(PI_BOUNCE2
);
4685 // 0xc7 Bounce:SpellLevel
4686 int fx_bounce_spelllevel (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4688 if (0) printf( "fx_bounce_spellevel (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4689 STAT_BIT_OR( IE_BOUNCE
, BNC_LEVEL
);
4690 target
->AddPortraitIcon(PI_BOUNCE2
);
4694 // 0xc8 Bounce:SpellLevelDec
4695 int fx_bounce_spelllevel_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4697 if (0) printf( "fx_bounce_spellevel_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4698 STAT_BIT_OR( IE_BOUNCE
, BNC_LEVEL_DEC
);
4699 target
->AddPortraitIcon(PI_BOUNCE
);
4703 //0xc9 Protection:SpellLevelDec
4704 int fx_protection_spelllevel_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4706 if (0) printf( "fx_protection_spelllevel_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4707 STAT_BIT_OR( IE_IMMUNITY
, IMM_LEVEL_DEC
);
4708 target
->AddPortraitIcon(PI_BOUNCE2
);
4712 //0xca Bounce:School
4713 int fx_bounce_school (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4715 if (0) printf( "fx_bounce_school (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4716 STAT_BIT_OR( IE_BOUNCE
, BNC_SCHOOL
);
4717 target
->AddPortraitIcon(PI_BOUNCE2
);
4721 // 0xcb Bounce:SecondaryType
4722 int fx_bounce_secondary_type (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4724 if (0) printf( "fx_bounce_secondary_type (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4725 STAT_BIT_OR( IE_BOUNCE
, BNC_SECTYPE
);
4726 target
->AddPortraitIcon(PI_BOUNCE2
);
4730 // 0xcc //resist school
4731 int fx_protection_school (Scriptable
* /*Owner*/, Actor
* target
, Effect
*fx
)
4733 if (0) printf( "fx_protection_school (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4734 STAT_BIT_OR( IE_IMMUNITY
, IMM_SCHOOL
);
4738 // 0xcd //resist sectype
4739 int fx_protection_secondary_type (Scriptable
* /*Owner*/, Actor
* target
, Effect
*fx
)
4741 if (0) printf( "fx_protection_secondary_type (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4742 STAT_BIT_OR( IE_IMMUNITY
, IMM_SECTYPE
);
4746 //0xce Protection:Spell
4747 int fx_resist_spell (Scriptable
* /*Owner*/, Actor
* target
, Effect
*fx
)
4749 if (0) printf( "fx_resist_spell (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
4750 if (strnicmp(fx
->Resource
,fx
->Source
,sizeof(fx
->Resource
)) ) {
4751 STAT_BIT_OR( IE_IMMUNITY
, IMM_RESOURCE
);
4754 //this has effect only on first apply, it will stop applying the spell
4758 // ??? Protection:SpellDec
4759 int fx_resist_spell_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
*fx
)
4761 if (0) printf( "fx_resist_spell_dec (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
4762 if (strnicmp(fx
->Resource
,fx
->Source
,sizeof(fx
->Resource
)) ) {
4763 STAT_BIT_OR( IE_IMMUNITY
, IMM_RESOURCE_DEC
);
4766 //this has effect only on first apply, it will stop applying the spell
4770 // 0xcf Bounce:Spell
4771 int fx_bounce_spell (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4773 if (0) printf( "fx_bounce_spell (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4774 STAT_BIT_OR( IE_BOUNCE
, BNC_RESOURCE
);
4778 // ??? Bounce:SpellDec
4779 int fx_bounce_spell_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4781 if (0) printf( "fx_bounce_spell (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
4782 STAT_BIT_OR( IE_BOUNCE
, BNC_RESOURCE_DEC
);
4786 // 0xd0 MinimumHPModifier
4787 // the original engine didn't allow modifying of this stat
4788 // it allowed only setting it, and only by one instance
4789 int fx_minimum_hp_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4791 if (0) printf( "fx_minimum_hp_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4793 STAT_MOD( IE_MINHITPOINTS
);
4797 //0xd1 PowerWordKill
4798 int fx_power_word_kill (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4800 if (0) printf( "fx_power_word_kill (%2d): HP: %d Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4803 if (fx
->Parameter1
) {
4804 limit
= fx
->Parameter1
;
4806 //normally this would work only with hitpoints
4807 //but why not add some extra features
4808 ieDword stat
= target
->GetStat (fx
->Parameter2
&0xffff);
4811 target
->Die( Owner
);
4813 return FX_NOT_APPLIED
;
4816 //0xd2 PowerWordStun
4817 int fx_power_word_stun (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4819 if (0) printf( "fx_power_word_stun (%2d): HP: %d Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4822 if (fx
->Parameter1
) {
4823 limit
= fx
->Parameter1
;
4825 //normally this would work only with hitpoints
4826 //but why not add some extra features
4827 ieDword stat
= target
->GetStat (fx
->Parameter2
&0xffff);
4828 ieDword x
= fx
->Parameter2
>>16; //dice sides
4831 return FX_NOT_APPLIED
;
4834 stat
= (stat
* 3 + limit
- 1) / limit
;
4835 //delay will be calculated as 1dx/2dx/3dx
4836 //depending on the current hitpoints (or the stat in param2)
4837 stat
= core
->Roll(stat
,x
?x
:4,0) * core
->Time
.round_size
;
4838 fx
->Duration
= core
->GetGame()->GameTime
+stat
;
4839 fx
->TimingMode
= FX_DURATION_ABSOLUTE
;
4840 fx
->Opcode
= EffectQueue::ResolveEffect(fx_set_stun_state_ref
);
4841 return fx_set_stun_state(Owner
,target
,fx
);
4844 //0xd3 State:Imprisonment (avatar removal plus portrait icon)
4845 int fx_imprisonment (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4847 if (0) printf( "fx_inprisonment (%2d)\n", fx
->Opcode
);
4848 target
->SetMCFlag(MC_HIDDEN
, BM_OR
);
4849 target
->AddPortraitIcon(PI_PRISON
);
4853 //0xd4 Cure:Imprisonment
4854 static EffectRef fx_imprisonment_ref
={"Imprisonment",NULL
,-1};
4855 static EffectRef fx_maze_ref
={"Maze",NULL
,-1};
4857 int fx_freedom (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4859 if (0) printf( "fx_freedom (%2d)\n", fx
->Opcode
);
4860 target
->fxqueue
.RemoveAllEffects( fx_imprisonment_ref
);
4861 target
->fxqueue
.RemoveAllEffects( fx_maze_ref
);
4862 return FX_NOT_APPLIED
;
4866 int fx_maze (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4868 if (0) printf( "fx_maze (%2d)\n", fx
->Opcode
);
4869 target
->SetMCFlag(MC_HIDDEN
, BM_OR
);
4870 target
->AddPortraitIcon(PI_MAZE
);
4875 int fx_select_spell (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
4877 if (0) printf( "fx_select_spell (%2d) %d\n", fx
->Opcode
, fx
->Parameter2
);
4878 //if parameter2==0 -> cast spells from 2da (all spells listed in 2da)
4879 //if parameter2==1 -> cast spells from book (all known spells, no need of memorize)
4880 return FX_NOT_APPLIED
;
4883 // 0xd7 PlayVisualEffect
4884 static EffectRef fx_protection_from_animation_ref
={"Protection:Animation",NULL
,-1};
4885 int fx_play_visual_effect (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4887 if (0) printf( "fx_play_visual_effect (%2d): Resource: %s Type: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
4889 //this is in the original engine (dead actors lose this effect)
4890 if (STATE_GET( STATE_DEAD
) ) {
4891 return FX_NOT_APPLIED
;
4894 //delay action until area is loaded to avoid crash
4895 Map
*map
= target
->GetCurrentArea();
4896 if (!map
) return FX_APPLIED
;
4898 //if it is sticky, don't add it if it is already played
4899 if (fx
->Parameter2
) {
4900 ScriptedAnimation
*vvc
= target
->GetVVCCell(fx
->Resource
);
4907 if (target
->fxqueue
.HasEffectWithResource(fx_protection_from_animation_ref
,fx
->Resource
)) {
4908 //effect supressed by opcode 0x128
4914 ScriptedAnimation
* sca
= gamedata
->GetScriptedAnimation(fx
->Resource
, false);
4916 //don't crash on nonexistent resources
4918 return FX_NOT_APPLIED
;
4921 if (fx
->TimingMode
!=FX_DURATION_INSTANT_PERMANENT
) {
4922 sca
->SetDefaultDuration(fx
->Duration
-core
->GetGame()->GameTime
);
4924 if (fx
->Parameter2
== 1) {
4925 //play over target (sticky)
4926 sca
->effect_owned
= true;
4927 target
->AddVVCell( sca
);
4932 if (fx
->Parameter2
== 2 || !target
) {
4933 sca
->XPos
= fx
->PosX
;
4934 sca
->YPos
= fx
->PosY
;
4936 sca
->XPos
= target
->Pos
.x
;
4937 sca
->YPos
= target
->Pos
.y
;
4940 map
->AddVVCell( sca
);
4941 return FX_NOT_APPLIED
;
4944 //d8 LevelDrainModifier
4946 static EffectRef fx_leveldrain_ref
={"LevelDrainModifier",NULL
,-1};
4948 // FIXME: BG2 level drain uses parameter3 to decrease the MaxHp, and parameter4 to decrease level. (unset)
4949 int fx_leveldrain_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
4951 if (0) printf( "fx_leveldrain_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter1
);
4953 //never subtract more than the maximum hitpoints
4954 ieDword x
= STAT_GET(IE_MAXHITPOINTS
)-1;
4955 if (fx
->Parameter1
*4<x
) {
4958 STAT_ADD(IE_LEVELDRAIN
, fx
->Parameter1
);
4959 STAT_SUB(IE_MAXHITPOINTS
, x
);
4960 STAT_SUB(IE_SAVEVSDEATH
, fx
->Parameter1
);
4961 STAT_SUB(IE_SAVEVSWANDS
, fx
->Parameter1
);
4962 STAT_SUB(IE_SAVEVSPOLY
, fx
->Parameter1
);
4963 STAT_SUB(IE_SAVEVSBREATH
, fx
->Parameter1
);
4964 STAT_SUB(IE_SAVEVSSPELL
, fx
->Parameter1
);
4965 target
->AddPortraitIcon(PI_LEVELDRAIN
);
4966 //decrease current hitpoints on first apply
4967 if (fx
->FirstApply
) {
4968 //current hitpoints don't have base/modified, only current
4969 BASE_SUB(IE_HITPOINTS
, x
);
4971 // TODO: lore, thieving
4976 static EffectRef fx_sleep_ref
={"State:Sleep",NULL
,-1};
4978 int fx_power_word_sleep (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
4980 if (0) printf( "fx_power_word_sleep (%2d): HP: %d Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
4983 if (fx
->Parameter1
) {
4984 limit
= fx
->Parameter1
;
4987 ieDword stat
= target
->GetStat (fx
->Parameter2
&0xffff);
4988 ieDword x
= fx
->Parameter2
>>16; //rounds
4992 return FX_NOT_APPLIED
;
4994 //translate this effect to a normal sleep effect
4996 fx
->Duration
= core
->GetGame()->GameTime
+x
*core
->Time
.round_size
;
4997 fx
->TimingMode
= FX_DURATION_ABSOLUTE
;
4998 fx
->Opcode
= EffectQueue::ResolveEffect(fx_sleep_ref
);
5000 return fx_set_unconscious_state(Owner
,target
,fx
);
5003 // 0xda StoneSkinModifier
5004 int fx_stoneskin_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5006 if (0) printf( "fx_stoneskin_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter1
);
5007 if (!fx
->Parameter1
) {
5008 return FX_NOT_APPLIED
;
5011 //dead actors lose this effect
5012 if (STATE_GET( STATE_DEAD
) ) {
5013 return FX_NOT_APPLIED
;
5016 //this is the bg2 style stoneskin, not normally using spell states
5017 //but this way we can support hybrid games
5018 if (fx
->Parameter2
) {
5019 target
->SetSpellState(SS_IRONSKIN
);
5020 //gradient for iron skins?
5022 target
->SetSpellState(SS_STONESKIN
);
5023 SetGradient(target
, 14);
5025 STAT_SET(IE_STONESKINS
, fx
->Parameter1
);
5026 target
->AddPortraitIcon(PI_STONESKIN
);
5030 //0xdb ac vs creature type (general effect)
5032 int fx_dispel_school (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5036 if (0) printf( "fx_dispel_school (%2d): Level: %d Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5037 target
->fxqueue
.RemoveLevelEffects(Removed
, fx
->Parameter1
, RL_MATCHSCHOOL
, fx
->Parameter2
);
5038 return FX_NOT_APPLIED
;
5040 //0xdd DispelSecondaryType
5041 int fx_dispel_secondary_type (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5045 if (0) printf( "fx_dispel_secondary_type (%2d): Level: %d Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5046 target
->fxqueue
.RemoveLevelEffects(Removed
, fx
->Parameter1
, RL_MATCHSECTYPE
, fx
->Parameter2
);
5047 return FX_NOT_APPLIED
;
5050 //0xde RandomTeleport
5051 int fx_teleport_field (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5053 if (0) printf( "fx_teleport_field (%2d): Distance: %d\n", fx
->Opcode
, fx
->Parameter1
);
5055 Map
*map
= target
->GetCurrentArea();
5057 return FX_NOT_APPLIED
;
5059 //the origin is the effect's target point
5060 Point
p(fx
->PosX
+core
->Roll(1,fx
->Parameter1
*2,-(signed) (fx
->Parameter1
)),
5061 fx
->PosY
+core
->Roll(1,fx
->Parameter1
*2,-(signed) (fx
->Parameter1
)) );
5063 target
->SetPosition( p
, true, 0);
5064 return FX_NOT_APPLIED
;
5067 //0xdf //Protection:SchoolDec
5068 int fx_protection_school_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5070 if (0) printf( "fx_protection_school_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
5071 if (fx
->Parameter1
) {
5072 STAT_BIT_OR( IE_IMMUNITY
, IMM_SCHOOL_DEC
);
5075 return FX_NOT_APPLIED
;
5078 //0xe0 Cure:LevelDrain
5080 int fx_cure_leveldrain (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5082 if (0) printf( "fx_cure_leveldrain (%2d)\n", fx
->Opcode
);
5083 //all level drain removed at once???
5084 //if not, then find old effect, remove a number
5085 target
->fxqueue
.RemoveAllEffects( fx_leveldrain_ref
);
5086 return FX_NOT_APPLIED
;
5090 //gemrb special: speed and color are custom
5091 int fx_reveal_magic (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5093 if (0) printf( "fx_reveal_magic (%2d)\n", fx
->Opcode
);
5094 if (target
->fxqueue
.HasAnyDispellableEffect()) {
5095 if (!fx
->Parameter1
) {
5096 fx
->Parameter1
=0xff00; //blue
5099 int speed
= (fx
->Parameter2
>> 16) & 0xFF;
5100 if (!speed
) speed
=30;
5101 target
->SetColorMod(0xff, RGBModifier::ADD
, speed
,
5102 fx
->Parameter1
>> 8, fx
->Parameter1
>> 16,
5103 fx
->Parameter1
>> 24, 0);
5105 return FX_NOT_APPLIED
;
5108 //0xe2 Protection:SecondaryTypeDec
5109 int fx_protection_secondary_type_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5111 if (0) printf( "fx_protection_secondary_type_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
5112 if (fx
->Parameter1
) {
5113 STAT_BIT_OR( IE_IMMUNITY
, IMM_SECTYPE_DEC
);
5116 return FX_NOT_APPLIED
;
5119 //0xe3 Bounce:SchoolDecrement
5120 int fx_bounce_school_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5122 if (0) printf( "fx_bounce_school_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
5123 STAT_BIT_OR( IE_BOUNCE
, BNC_SCHOOL_DEC
);
5124 target
->AddPortraitIcon(PI_BOUNCE2
);
5128 //0xe4 Bounce:SecondaryTypeDecrement
5129 int fx_bounce_secondary_type_dec (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5131 if (0) printf( "fx_bounce_secondary_type_dec (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
5132 STAT_BIT_OR( IE_BOUNCE
, BNC_SECTYPE_DEC
);
5133 target
->AddPortraitIcon(PI_BOUNCE2
);
5137 //0xe5 DispelSchoolOne
5138 int fx_dispel_school_one (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5142 if (0) printf( "fx_dispel_school_one (%2d): Level: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5143 target
->fxqueue
.RemoveLevelEffects(Removed
, fx
->Parameter1
, RL_MATCHSCHOOL
|RL_REMOVEFIRST
, fx
->Parameter2
);
5144 return FX_NOT_APPLIED
;
5147 //0xe6 DispelSecondaryTypeOne
5148 int fx_dispel_secondary_type_one (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5152 if (0) printf( "fx_dispel_secondary_type_one (%2d): Level: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5153 target
->fxqueue
.RemoveLevelEffects(Removed
, fx
->Parameter1
, RL_MATCHSECTYPE
|RL_REMOVEFIRST
, fx
->Parameter2
);
5154 return FX_NOT_APPLIED
;
5158 int fx_timestop (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5160 if (0) printf( "fx_timestop (%2d)\n", fx
->Opcode
);
5161 core
->GetGame()->TimeStop(target
, fx
->Duration
);
5162 return FX_NOT_APPLIED
;
5165 //0xe8 CastSpellOnCondition
5166 int fx_cast_spell_on_condition (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5168 if (0) printf( "fx_cast_spell_on_condition (%2d): Target: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5170 if (fx
->FirstApply
&& fx
->Parameter3
) {
5171 target
->spellbook
.HaveSpell( fx
->Resource
, HS_DEPLETE
);
5172 target
->spellbook
.HaveSpell( fx
->Resource2
, HS_DEPLETE
);
5173 target
->spellbook
.HaveSpell( fx
->Resource3
, HS_DEPLETE
);
5174 target
->spellbook
.HaveSpell( fx
->Resource4
, HS_DEPLETE
);
5177 //get subject of check
5178 Actor
*actor
= NULL
;
5179 Map
*map
= target
->GetCurrentArea();
5180 switch(fx
->Parameter1
) {
5182 case 0: actor
= target
; break;
5184 case 1: actor
= map
->GetActorByGlobalID(target
->LastHitter
); break;
5187 //case 2: actor = map->GetActorByGlobalID(target->LastSeen); break;
5188 case 2: actor
= GetNearestEnemyOf(map
, target
, 0); break;
5190 case 3: actor
= map
->GetActorByGlobalID(target
->LastSeen
); break;
5197 switch(fx
->Parameter2
) {
5198 case COND_GOTHIT
: //on hit
5199 condition
= target
->LastDamage
;
5202 condition
= PersonalDistance(actor
, target
)<30;
5205 condition
= actor
->GetBase(IE_HITPOINTS
)<actor
->GetStat(IE_MAXHITPOINTS
)/2;
5208 condition
= actor
->GetBase(IE_HITPOINTS
)<actor
->GetStat(IE_MAXHITPOINTS
)/4;
5211 condition
= actor
->GetBase(IE_HITPOINTS
)<actor
->GetStat(IE_MAXHITPOINTS
)/10;
5214 condition
= actor
->GetStat(IE_STATE_ID
) & STATE_CANTMOVE
;
5217 condition
= actor
->GetStat(IE_STATE_ID
) & STATE_POISONED
;
5219 case COND_ATTACKED
: // once per round
5220 condition
= actor
->LastHitter
;
5222 case COND_NEAR4
: // closer than 4'
5223 condition
= PersonalDistance(actor
, target
)<4;
5225 case COND_NEAR10
: // closer than 10'
5226 condition
= PersonalDistance(actor
, target
)<10;
5228 case COND_EVERYROUND
:
5231 case COND_TOOKDAMAGE
:
5232 condition
= actor
->LastDamage
;
5239 core
->ApplySpell(fx
->Resource
, actor
, Owner
, fx
->Power
);
5240 core
->ApplySpell(fx
->Resource2
, actor
, Owner
, fx
->Power
);
5241 core
->ApplySpell(fx
->Resource3
, actor
, Owner
, fx
->Power
);
5242 core
->ApplySpell(fx
->Resource4
, actor
, Owner
, fx
->Power
);
5243 if (fx
->Parameter3
) {
5244 return FX_NOT_APPLIED
;
5251 int fx_proficiency (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5253 if (0) printf( "fx_proficiency (%2d): Value: %d, Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5255 if (fx
->Parameter2
>=MAX_STATS
) return FX_NOT_APPLIED
;
5257 //this opcode works only if the previous value was smaller
5258 if (STAT_GET(fx
->Parameter2
)<fx
->Parameter1
) {
5259 STAT_SET (fx
->Parameter2
, fx
->Parameter1
);
5264 // 0xea CreateContingency
5265 static EffectRef fx_contingency_ref
={"CastSpellOnCondition",NULL
,-1};
5267 int fx_create_contingency (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5269 if (0) printf( "fx_create_contingency (%2d): Level: %d, Count: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5271 if (target
->fxqueue
.HasEffectWithSource(fx_contingency_ref
, fx
->Source
)) {
5272 displaymsg
->DisplayConstantStringName(STR_CONTDUP
, 0xf0f0f0, target
);
5273 return FX_NOT_APPLIED
;
5276 if (target
->InParty
) {
5277 Variables
*dict
= core
->GetDictionary();
5279 dict
->SetAt( "P0", target
->InParty
);
5280 dict
->SetAt( "P1", fx
->Parameter1
);
5281 dict
->SetAt( "P2", fx
->Parameter2
);
5282 core
->SetEventFlag(EF_SEQUENCER
);
5284 return FX_NOT_APPLIED
;
5288 #define WB_TOWARDS 1
5291 #define WB_AWAYOWNDIR 4
5294 int fx_wing_buffet (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5296 if (0) printf( "fx_wing_buffet (%2d): Value: %d, Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5297 //create movement in actor
5300 switch(fx
->Parameter2
) {
5303 dir
= GetOrient(Owner
->Pos
, target
->Pos
);
5306 dir
= GetOrient(target
->Pos
, Owner
->Pos
);
5309 dir
= fx
->Parameter3
;
5312 dir
= target
->GetOrientation();
5315 dir
= target
->GetOrientation()^8;
5318 //could be GL_REBOUND too :)
5319 //add effect to alter target's stance
5320 target
->MoveLine( fx
->Parameter1
, GL_NORMAL
, dir
);
5321 return FX_NOT_APPLIED
;
5324 // 0xec ProjectImage
5326 static EffectRef fx_puppetmarker_ref
={"PuppetMarker",NULL
,-1};
5328 int fx_puppet_master (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5330 const char * resref
= NULL
;
5332 if (0) printf( "fx_puppet_master (%2d): Value: %d, Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5333 STAT_SET (IE_PUPPETMASTERTYPE
, fx
->Parameter1
);
5335 //copyself doesn't copy scripts, so the script clearing code is not needed
5336 Actor
*copy
= target
->CopySelf(fx
->Parameter2
== 1);
5338 Effect
*newfx
= EffectQueue::CreateUnsummonEffect(fx
);
5340 core
->ApplyEffect(newfx
, copy
, copy
);
5346 //intentionally 7, to leave room for the last letter
5347 strnlwrcpy(script
,target
->GetScript(SCR_CLASS
),7);
5348 //no need of buffer defense as long as you don't mess with the 7 above
5350 //if the caster is inparty, the script is turned off by the AI disable flag
5351 copy
->SetScript(script
, SCR_CLASS
, target
->InParty
!=0);
5353 switch(fx
->Parameter2
)
5357 //set the gender to illusionary, so ids matching will work
5358 copy
->SetBase(IE_SEX
, SEX_ILLUSION
);
5359 copy
->SetBase(IE_MAXHITPOINTS
, copy
->GetBase(IE_MAXHITPOINTS
)/2);
5363 copy
->SetBase(IE_SEX
, SEX_ILLUSION
);
5366 resref
= "simulacr";
5367 // healable level drain
5368 // FIXME: second generation simulacri are supposedly at a different level:
5369 // level = original caster - caster / 2; eg. lvl 32 -> 16 -> 24 -> 20 -> 22 -> 21
5370 newfx
= EffectQueue::CreateEffect(fx_leveldrain_ref
, copy
->GetXPLevel(1)/2, 0, FX_DURATION_INSTANT_PERMANENT
);
5372 core
->ApplyEffect(newfx
, copy
, copy
);
5377 resref
= fx
->Resource
;
5381 core
->ApplySpell(resref
,copy
,copy
,0);
5384 //FIXME: parameter1 is unsure, but something similar to what the original engine has there
5385 newfx
= EffectQueue::CreateEffectCopy(fx
, fx_puppetmarker_ref
, target
->InParty
-1, fx
->Parameter2
);
5387 core
->ApplyEffect(newfx
, copy
, copy
);
5390 return FX_NOT_APPLIED
;
5393 // 0xed PuppetMarker
5394 int fx_puppet_marker (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5396 if (0) printf( "fx_puppet_marker (%2d): Value: %d, Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5397 //actually the Type is in parameter2 and the ID is in parameter1
5398 //but for some reason the defines are in the opposite order
5399 STAT_SET (IE_PUPPETTYPE
, fx
->Parameter1
); //cb4 - the ID of the controller
5400 STAT_SET (IE_PUPPETID
, fx
->Parameter2
); //cb8 - the control type
5404 // 0xee Disintegrate
5405 int fx_disintegrate (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5407 if (0) printf( "fx_disintegrate (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5408 if (EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
5409 //convert it to a death opcode or apply the new effect?
5410 fx
->Opcode
= EffectQueue::ResolveEffect(fx_death_ref
);
5411 fx
->TimingMode
= FX_DURATION_INSTANT_PERMANENT
;
5413 fx
->Parameter2
= 0x200;
5416 return FX_NOT_APPLIED
;
5420 // 1 view not explored sections too
5421 // 2 param1=range (otherwise visualrange)
5422 // 4 point already set (otherwise use gui)
5423 // 8 use line of sight
5424 #define FS_UNEXPLORED 1
5425 #define FS_VISUALRANGE 2
5426 #define FS_HASPOINT 4
5429 int fx_farsee (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5431 if (0) printf( "fx_farsee (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5432 Map
*map
= target
->GetCurrentArea();
5437 if (!(fx
->Parameter2
&FS_VISUALRANGE
)) {
5438 fx
->Parameter1
=STAT_GET(IE_VISUALRANGE
);
5439 fx
->Parameter2
|=FS_VISUALRANGE
;
5442 if (target
->InParty
) {
5443 //don't start graphical interface if actor isn't in party
5444 if (!(fx
->Parameter2
&FS_HASPOINT
)) {
5445 //start graphical interface
5446 //it will do all the rest of the opcode
5447 //using RevealMap guiscript action
5448 core
->EventFlag
|=EF_SHOWMAP
;
5449 return FX_NOT_APPLIED
;
5453 Point
p(fx
->PosX
, fx
->PosY
);
5455 //don't explore unexplored points
5456 if (!(fx
->Parameter2
&FS_UNEXPLORED
)) {
5457 if (!map
->IsVisible(p
, 1)) {
5458 return FX_NOT_APPLIED
;
5461 map
->ExploreMapChunk(p
, fx
->Parameter1
, fx
->Parameter2
&FS_LOS
);
5462 return FX_NOT_APPLIED
;
5466 int fx_remove_portrait_icon (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5468 if (0) printf( "fx_remove_portrait_icon (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
5469 target
->fxqueue
.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref
, fx
->Parameter2
);
5470 return FX_NOT_APPLIED
;
5472 // 0xf1 control creature (same as charm)
5474 // 0xF2 Cure:Confusion
5475 static EffectRef fx_confused_state_ref
={"State:Confused",NULL
,-1};
5477 int fx_cure_confused_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5479 if (0) printf( "fx_cure_confused_state (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5480 BASE_STATE_CURE( STATE_CONFUSED
);
5481 target
->fxqueue
.RemoveAllEffects(fx_confused_state_ref
);
5482 return FX_NOT_APPLIED
;
5485 // 0xf3 DrainItems (this is disabled in ToB)
5486 int fx_drain_items (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5488 if (0) printf( "fx_drain_items (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5489 ieDword i
=fx
->Parameter1
;
5491 //deplete magic item = 0
5492 //deplete weapon = 1
5493 target
->inventory
.DepleteItem(fx
->Parameter2
);
5495 return FX_NOT_APPLIED
;
5498 int fx_drain_spells (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5500 if (0) printf( "fx_drain_spells (%2d): Count: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5501 ieDword i
=fx
->Parameter1
;
5502 if (fx
->Parameter2
) {
5504 if (!target
->spellbook
.DepleteSpell(IE_SPELL_TYPE_PRIEST
)) {
5508 return FX_NOT_APPLIED
;
5511 if (!target
->spellbook
.DepleteSpell(IE_SPELL_TYPE_WIZARD
)) {
5515 return FX_NOT_APPLIED
;
5517 // 0xf5 CheckForBerserk
5518 int fx_checkforberserk_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5520 if (0) printf( "fx_checkforberserk_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5521 STAT_SET( IE_CHECKFORBERSERK
, fx
->Parameter2
);
5524 // 0xf6 BerserkStage1Modifier
5525 int fx_berserkstage1_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5527 if (0) printf( "fx_berserkstage1_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5528 STAT_SET( IE_BERSERKSTAGE1
, fx
->Parameter2
);
5531 // 0xf7 BerserkStage2Modifier
5532 int fx_berserkstage2_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5534 if (0) printf( "fx_berserkstage2_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5535 STAT_SET( IE_BERSERKSTAGE2
, fx
->Parameter2
);
5536 STATE_SET (STATE_BERSERK
);
5540 // 0xf8 set melee effect
5541 // adds effect to melee attacks (for monks, asssasins, fighter hlas, ...)
5543 int fx_melee_effect (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
) {
5544 if (1) printf( "fx_melee_effect (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
5546 // are we just about to attack? Try later otherwise
5547 if (!target
->GetAttackProjectile()) {
5551 if ((target
->GetAttackStyle()&3) == 2) { //WEAPON_RANGED
5552 // wrong effect, try later
5556 Point
p(fx
->PosX
, fx
->PosY
);
5557 Effect
*extrafx
= core
->GetEffect(fx
->Resource
, fx
->Power
, p
);
5558 //core->GetEffect is a borrowed reference, don't delete it
5560 return FX_NOT_APPLIED
;
5562 extrafx
->Target
= FX_TARGET_PRESET
;
5564 // attach it to the attack projectile
5565 target
->GetAttackProjectile()->GetEffects()->AddEffect(extrafx
, true);
5570 // 0xf9 set missile effect
5571 // adds effect to ranged attacks (archers, ...)
5573 int fx_ranged_effect (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
) {
5574 if (1) printf( "fx_ranged_effect (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
5576 // are we just about to attack? Try later otherwise
5577 if (!target
->GetAttackProjectile()) {
5581 if ((target
->GetAttackStyle()&3) != 2) { // WEAPON_RANGED
5582 // wrong effect, try later
5586 Point
p(fx
->PosX
, fx
->PosY
);
5587 Effect
*extrafx
= core
->GetEffect(fx
->Resource
, fx
->Power
, p
);
5588 //core->GetEffect is a borrowed reference, don't delete it
5590 return FX_NOT_APPLIED
;
5592 extrafx
->Target
= FX_TARGET_PRESET
;
5594 // attach it to the attack projectile
5595 target
->GetAttackProjectile()->GetEffects()->AddEffect(extrafx
, true);
5600 // 0xfa DamageLuckModifier
5601 int fx_damageluck_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5603 if (0) printf( "fx_damageluck_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5604 STAT_MOD( IE_DAMAGELUCK
);
5610 int fx_change_bardsong (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5612 if (0) printf( "fx_change_bardsong (%2d): %s\n", fx
->Opcode
, fx
->Resource
);
5613 memcpy(target
->BardSong
, fx
->Resource
, 8);
5618 int fx_set_area_effect (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5620 if (0) printf( "fx_set_trap (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5621 ieDword skill
, roll
;
5624 map
= target
->GetCurrentArea();
5625 if (!map
) return FX_NOT_APPLIED
;
5629 //check if trap count is over an amount (only saved traps count)
5630 //actually, only projectiles in trigger phase should count here
5631 if (map
->GetTrapCount(iter
)>6) {
5632 displaymsg
->DisplayConstantStringName(STR_NOMORETRAP
, 0xf0f0f0, target
);
5633 return FX_NOT_APPLIED
;
5636 //check if we are under attack
5637 if (GetNearestEnemyOf(map
, target
, ORIGIN_SEES_ENEMY
|ENEMY_SEES_ORIGIN
)) {
5638 displaymsg
->DisplayConstantStringName(STR_MAYNOTSETTRAP
, 0xf0f0f0, target
);
5639 return FX_NOT_APPLIED
;
5642 if (Owner
->Type
==ST_ACTOR
) {
5643 skill
= ((Actor
*)Owner
)->GetStat(IE_SETTRAPS
);
5644 roll
= core
->Roll(1,100,0);
5652 displaymsg
->DisplayConstantStringName(STR_SNAREFAILED
, 0xf0f0f0, target
);
5653 //TODO check luck and do some damage effect on target
5654 return FX_NOT_APPLIED
;
5657 displaymsg
->DisplayConstantStringName(STR_SNARESUCCEED
, 0xf0f0f0, target
);
5658 Owner
->CastSpellPoint(fx
->Resource
, target
->Pos
, false);
5659 return FX_NOT_APPLIED
;
5663 int fx_set_map_note (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5665 if (0) printf( "fx_set_map_note (%2d): StrRef: %d Color: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5666 Scriptable
*marker
= target
?target
:Owner
;
5667 Map
*map
= marker
->GetCurrentArea();
5668 if (!map
) return FX_APPLIED
; //delay effect
5669 Point
p(fx
->PosX
, fx
->PosY
);
5670 char *text
= core
->GetString(fx
->Parameter1
, 0);
5671 map
->AddMapNote(p
, fx
->Parameter2
, text
, fx
->Parameter1
);
5672 return FX_NOT_APPLIED
;
5675 // 0xfe RemoveMapNote
5676 int fx_remove_map_note (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5678 if (0) printf( "fx_remove_map_note (%2d)\n", fx
->Opcode
);
5679 Scriptable
*marker
= target
?target
:Owner
;
5680 Map
*map
= marker
->GetCurrentArea();
5681 if (!map
) return FX_APPLIED
; //delay effect
5682 Point
p(fx
->PosX
, fx
->PosY
);
5683 map
->RemoveMapNote(p
);
5684 return FX_NOT_APPLIED
;
5687 // 0xff Item:CreateDays
5688 int fx_create_item_days (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5690 if (0) printf( "fx_create_item_days (%2d)\n", fx
->Opcode
);
5691 target
->inventory
.AddSlotItemRes( fx
->Resource
, SLOT_ONLYINVENTORY
, fx
->Parameter1
, fx
->Parameter3
, fx
->Parameter4
);
5692 if ((fx
->TimingMode
&0xff) == FX_DURATION_INSTANT_LIMITED
) {
5693 //if this effect has expiration, then it will remain as a remove_item
5694 //on the effect queue, inheriting all the parameters
5695 //duration needs a hack (recalculate it for days)
5696 //no idea if this multiplier is ok
5697 fx
->Duration
+=(fx
->Duration
-core
->GetGame()->GameTime
)*2400;
5698 fx
->Opcode
=EffectQueue::ResolveEffect(fx_remove_inventory_item_ref
);
5699 fx
->TimingMode
=FX_DURATION_DELAY_PERMANENT
;
5702 return FX_NOT_APPLIED
;
5705 // 0x100 Sequencer:Store
5706 int fx_store_spell_sequencer(Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5708 if (0) printf( "fx_store_spell_sequencer (%2d)\n", fx
->Opcode
);
5709 //just display the spell sequencer portrait icon
5710 target
->AddPortraitIcon(PI_SEQUENCER
);
5711 if (fx
->FirstApply
&& fx
->Parameter3
) {
5712 target
->spellbook
.HaveSpell( fx
->Resource
, HS_DEPLETE
);
5713 target
->spellbook
.HaveSpell( fx
->Resource2
, HS_DEPLETE
);
5714 target
->spellbook
.HaveSpell( fx
->Resource3
, HS_DEPLETE
);
5715 target
->spellbook
.HaveSpell( fx
->Resource4
, HS_DEPLETE
);
5720 // 0x101 Sequencer:Create
5721 static EffectRef fx_spell_sequencer_active_ref
={"Sequencer:Store",NULL
,-1};
5723 int fx_create_spell_sequencer(Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5725 if (0) printf( "fx_create_spell_sequencer (%2d): Level: %d, Count: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5726 if (target
->fxqueue
.HasEffectWithSource(fx_spell_sequencer_active_ref
, fx
->Source
)) {
5727 displaymsg
->DisplayConstantStringName(STR_SEQDUP
, 0xf0f0f0, target
);
5728 return FX_NOT_APPLIED
;
5730 //just a call to activate the spell sequencer creation gui
5731 if (target
->InParty
) {
5732 Variables
*dict
= core
->GetDictionary();
5734 dict
->SetAt( "P0", target
->InParty
);
5735 dict
->SetAt( "P1", fx
->Parameter1
); //maximum level
5736 dict
->SetAt( "P2", fx
->Parameter2
| (2<<16) ); //count and target type
5737 core
->SetEventFlag(EF_SEQUENCER
);
5739 return FX_NOT_APPLIED
;
5742 // 0x102 Sequencer:Activate
5744 int fx_activate_spell_sequencer(Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5746 if (0) printf( "fx_activate_spell_sequencer (%2d): Resource: %s\n", fx
->Opcode
, fx
->Resource
);
5747 if (Owner
->Type
!=ST_ACTOR
) {
5748 return FX_NOT_APPLIED
;
5751 Effect
*sequencer
= ((Actor
*) Owner
)->fxqueue
.HasEffect(fx_spell_sequencer_active_ref
);
5753 //cast 1-4 spells stored in the spell sequencer
5754 core
->ApplySpell(sequencer
->Resource
, target
, Owner
, fx
->Power
);
5755 core
->ApplySpell(sequencer
->Resource2
, target
, Owner
, fx
->Power
);
5756 core
->ApplySpell(sequencer
->Resource3
, target
, Owner
, fx
->Power
);
5757 core
->ApplySpell(sequencer
->Resource4
, target
, Owner
, fx
->Power
);
5758 //remove the spell sequencer store effect
5759 sequencer
->TimingMode
=FX_DURATION_JUST_EXPIRED
;
5761 return FX_NOT_APPLIED
;
5764 // 0x103 SpellTrap (Protection:SpellLevelDec + recall spells)
5765 int fx_spelltrap(Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5767 if (0) printf( "fx_spelltrap (%2d): Count: %d, Level: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5768 if (fx
->Parameter3
) {
5769 target
->RestoreSpellLevel(fx
->Parameter3
, 0);
5772 if (fx
->Parameter1
<=0) {
5774 return FX_NOT_APPLIED
;
5776 target
->SetOverlay(OV_SPELLTRAP
);
5777 target
->AddPortraitIcon(PI_SPELLTRAP
);
5783 int fx_crash (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
5785 if (0) printf( "fx_crash (%2d): Param1: %d, Param2: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5786 return FX_NOT_APPLIED
;
5789 // 0x105 RestoreSpells
5790 int fx_restore_spell_level(Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5792 if (0) printf( "fx_restore_spell_level (%2d): Level: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5793 target
->RestoreSpellLevel(fx
->Parameter1
, fx
->Parameter2
);
5794 return FX_NOT_APPLIED
;
5796 // 0x106 VisualRangeModifier
5797 int fx_visual_range_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5799 if (0) printf( "fx_visual_range_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5800 STAT_MOD( IE_VISUALRANGE
);
5804 // 0x107 BackstabModifier
5805 int fx_backstab_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5807 if (0) printf( "fx_visual_range_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5808 //this is how it is done in the original engine, i don't know why they would do this
5809 //ctrl-r would probably remove it otherwise
5810 //Why they didn't fix it in the spell/item is beyond me
5811 if (fx
->TimingMode
==FX_DURATION_INSTANT_PERMANENT
)
5812 fx
->TimingMode
=FX_DURATION_INSTANT_PERMANENT_AFTER_BONUSES
;
5813 STAT_MOD( IE_BACKSTABDAMAGEMULTIPLIER
);
5818 int fx_drop_weapon (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5820 if (fx
->Resource
[0]) {
5821 target
->DropItem(fx
->Resource
, 0);
5822 return FX_NOT_APPLIED
;
5824 switch (fx
->Parameter2
) {
5826 target
->DropItem(-1, 0);
5829 target
->DropItem(target
->inventory
.GetEquippedSlot(), 0);
5832 target
->DropItem(fx
->Parameter1
, 0);
5835 return FX_NOT_APPLIED
;
5837 // 0x109 ModifyGlobalVariable
5838 int fx_modify_global_variable (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
5840 Game
*game
= core
->GetGame();
5841 //convert it to internal variable format
5842 if (!fx
->IsVariable
) {
5843 char *poi
=fx
->Resource
+8;
5844 memmove(poi
, fx
->Resource2
,8);
5846 memmove(poi
, fx
->Resource3
,8);
5848 memmove(poi
, fx
->Resource4
,8);
5853 if (!fx
->Resource
[0]) {
5854 strnuprcpy(fx
->Resource
,"RETURN_TO_LONELYWOOD",32);
5857 if (0) printf( "fx_modify_global_variable (%2d): Variable: %s Value: %d Type: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter1
, fx
->Parameter2
);
5858 if (fx
->Parameter2
) {
5860 //use resource memory area as variable name
5861 game
->locals
->Lookup(fx
->Resource
, var
);
5862 game
->locals
->SetAt(fx
->Resource
, var
+fx
->Parameter1
);
5864 game
->locals
->SetAt(fx
->Resource
, fx
->Parameter1
);
5866 return FX_NOT_APPLIED
;
5868 // 0x10a RemoveImmunity
5869 EffectRef immunity_effect_ref
={"Protection:Spell",NULL
,-1};
5871 int fx_remove_immunity(Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5873 if (0) printf( "fx_remove_immunity (%2d): %s\n", fx
->Opcode
, fx
->Resource
);
5874 target
->fxqueue
.RemoveAllEffectsWithResource(immunity_effect_ref
, fx
->Resource
);
5875 return FX_NOT_APPLIED
;
5878 // 0x10b protection from display string is a generic effect
5879 // 0x10c ExploreModifier
5880 int fx_explore_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5882 if (0) printf( "fx_explore_modifier (%2d)\n", fx
->Opcode
);
5883 if (fx
->Parameter2
) {
5885 STAT_SET (IE_EXPLORE
, fx
->Parameter1
);
5887 STAT_SET (IE_EXPLORE
, 1);
5891 // 0x10d ScreenShake
5892 int fx_screenshake (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
5894 if (0) printf( "fx_screenshake (%2d): Strength: %d\n", fx
->Opcode
, fx
->Parameter1
);
5895 core
->timer
->SetScreenShake( fx
->Parameter1
, fx
->Parameter1
, 1);
5899 // 0x10e Cure:CasterHold
5900 static EffectRef fx_pause_caster_modifier_ref
={"PauseTarget",NULL
,-1};
5902 int fx_unpause_caster (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5904 if (0) printf( "fx_unpause_caster (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5905 target
->fxqueue
.RemoveAllEffects(fx_pause_caster_modifier_ref
);
5906 return FX_NOT_APPLIED
;
5908 // 0x10f AvatarRemoval
5909 // 0x104 AvatarRemoval (iwd)
5910 int fx_avatar_removal (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5912 if (0) printf( "fx_avatar_removal (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5913 //FIXME: this is a permanent irreversible effect in IWD
5914 //if it is different in bg2, then create another effect
5915 //bg2 calls this SummonDisable
5916 BASE_SET(IE_AVATARREMOVAL
, 1);
5917 return FX_NOT_APPLIED
;
5920 /* note/TODO from Taimon:
5921 What happens at a lower level is that the engine recreates the entire stats on some changes to the creature. The application of an effect to the creature is one such change.
5922 Since the repeating effects are stored in a list inside those stats, they are being recreated every ai update, if there has been an effect application.
5923 The repeating effect itself internally uses a counter to store how often it has been called. And when this counter equals the period it fires of the effect. When the list is being recreated all those counters are lost.
5925 static EffectRef fx_apply_effect_repeat_ref
= {"ApplyEffectRepeat", NULL
, -1};
5926 // 0x110 ApplyEffectRepeat
5927 int fx_apply_effect_repeat (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
5929 ieDword i
; //moved here because msvc6 cannot handle it otherwise
5931 if (0) printf( "fx_apply_effect_repeat (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5933 Point
p(fx
->PosX
, fx
->PosY
);
5934 Effect
*newfx
= core
->GetEffect(fx
->Resource
, fx
->Power
, p
);
5935 //core->GetEffect is a borrowed reference, don't delete it
5937 return FX_NOT_APPLIED
;
5940 // don't apply the effect if a similar one is already applied with a shorter duration
5941 Effect
*oldfx
= target
->fxqueue
.HasEffect(fx_apply_effect_repeat_ref
);
5942 if (oldfx
&& oldfx
->Duration
< fx
->Duration
) {
5943 return FX_NOT_APPLIED
;
5946 switch (fx
->Parameter2
) {
5947 case 0: //once per second
5949 if (!(core
->GetGame()->GameTime
%AI_UPDATE_TIME
)) {
5950 core
->ApplyEffect(newfx
, target
, Owner
);
5953 case 2://param1 times every second
5954 if (!(core
->GetGame()->GameTime
%AI_UPDATE_TIME
)) {
5955 for (i
=0;i
<fx
->Parameter1
;i
++) {
5956 core
->ApplyEffect(newfx
, target
, Owner
);
5960 case 3: //once every Param1 second
5961 if (fx
->Parameter1
&& (core
->GetGame()->GameTime
%fx
->Parameter1
)) {
5962 core
->ApplyEffect(newfx
, target
, Owner
);
5965 case 4: //param3 times every Param1 second
5966 if (fx
->Parameter1
&& (core
->GetGame()->GameTime
%fx
->Parameter1
)) {
5967 for (i
=0;i
<fx
->Parameter3
;i
++) {
5968 core
->ApplyEffect(newfx
, target
, Owner
);
5976 // 0x111 RemoveProjectile
5977 int fx_remove_projectile (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
5979 //the list is now cached by Interface, no need of freeing it
5980 ieDword
*projectilelist
;
5983 if (0) printf( "fx_remove_projectile (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
5985 if (!target
) return FX_NOT_APPLIED
;
5986 Map
*area
= target
->GetCurrentArea();
5987 if (!area
) return FX_NOT_APPLIED
;
5989 switch (fx
->Parameter2
) {
5990 case 0: //standard bg2
5991 projectilelist
= core
->GetListFrom2DA("clearair");
5993 case 1: //you can give a 2da for projectile list (gemrb)
5994 projectilelist
= core
->GetListFrom2DA(fx
->Resource
);
5996 case 2: //or you can give one single projectile in param1 (gemrb)
5997 projectilelist
= (ieDword
*) malloc(2*sizeof(ieDword
));
5998 projectilelist
[0]=1;
5999 projectilelist
[1]=fx
->Parameter1
;
6002 return FX_NOT_APPLIED
;
6004 //The first element is the counter, so don't decrease the counter here
6005 Point
p(fx
->PosX
, fx
->PosY
);
6007 int i
= projectilelist
[0];
6010 ieDword projectile
= projectilelist
[i
];
6013 size_t cnt
= area
->GetProjectileCount(piter
);
6015 Projectile
*pro
= *piter
;
6016 if ((pro
->GetType()==projectile
) && pro
->PointInRadius(p
) ) {
6021 target
->fxqueue
.RemoveAllEffectsWithProjectile(projectile
);
6025 //this one was constructed by us
6026 if (fx
->Parameter2
==2) free(projectilelist
);
6027 return FX_NOT_APPLIED
;
6030 // 0x112 TeleportToTarget
6031 int fx_teleport_to_target (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6033 if (0) printf( "fx_teleport_to_target (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6034 if (STATE_GET(STATE_DEAD
)) {
6035 return FX_NOT_APPLIED
;
6038 Map
*map
= target
->GetCurrentArea();
6040 Actor
*victim
= map
->GetActorByGlobalID(target
->LastAttacker
);
6042 target
->SetPosition( victim
->Pos
, true, 0 );
6045 return FX_NOT_APPLIED
;
6047 // 0x113 HideInShadowsModifier
6048 int fx_hide_in_shadows_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6050 if (0) printf( "fx_hide_in_shadows_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6051 STAT_MOD( IE_HIDEINSHADOWS
);
6054 // 0x114 DetectIllusionsModifier
6055 int fx_detect_illusion_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6057 if (0) printf( "fx_detect_illusion_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6058 STAT_MOD( IE_DETECTILLUSIONS
);
6061 // 0x115 SetTrapsModifier
6062 int fx_set_traps_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6064 if (0) printf( "fx_set_traps_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6065 STAT_MOD( IE_SETTRAPS
);
6068 // 0x116 ToHitBonusModifier
6069 int fx_to_hit_bonus_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6071 if (0) printf( "fx_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6072 HandleBonus( target
, IE_HITBONUS
, fx
->Parameter1
, fx
->TimingMode
);
6076 // 0x117 RenableButton
6077 static EffectRef fx_disable_button_ref
={"DisableButton",NULL
,-1};
6079 int fx_renable_button (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6081 //removes the disable button effect
6082 if (0) printf( "fx_renable_button (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
6083 target
->fxqueue
.RemoveAllEffectsWithParam( fx_disable_button_ref
, fx
->Parameter2
);
6084 return FX_NOT_APPLIED
;
6086 // 0x118 ForceSurgeModifier
6087 int fx_force_surge_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6089 if (0) printf( "fx_force_surge_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6090 STAT_MOD( IE_FORCESURGE
);
6094 // 0x119 WildSurgeModifier
6095 int fx_wild_surge_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6097 if (0) printf( "fx_wild_surge_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6098 STAT_MOD( IE_SURGEMOD
);
6102 // 0x11a ScriptingState
6103 int fx_scripting_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6105 if (0) printf( "fx_scripting_state (%2d): Value: %d, Stat: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6107 //original engine didn't check boundaries, causing crashes
6108 //we allow only positive indices (some extra stats are still addressable)
6109 if (fx
->Parameter2
>100) {
6110 return FX_NOT_APPLIED
;
6112 //original engine used only single byte value, we allow full dword
6113 STAT_SET( IE_SCRIPTINGSTATE1
+fx
->Parameter2
, fx
->Parameter1
);
6117 // 0x11b ApplyEffectCurse
6118 int fx_apply_effect_curse (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6120 if (0) printf( "fx_apply_effect_curse (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6122 //this effect executes a file effect in place of this effect
6123 //the file effect inherits the target and the timingmode, but gets
6124 //a new chance to roll percents
6125 int ret
= FX_NOT_APPLIED
;
6130 if (EffectQueue::match_ids( target
, fx
->Parameter2
, fx
->Parameter1
) ) {
6131 Point
p(fx
->PosX
, fx
->PosY
);
6133 //apply effect, if the effect is a goner, then kill
6135 Effect
*newfx
= core
->GetEffect(fx
->Resource
, fx
->Power
, p
);
6137 Effect
*myfx
= new Effect
;
6138 memcpy(myfx
, newfx
, sizeof(Effect
));
6139 myfx
->random_value
= fx
->random_value
;
6140 myfx
->TimingMode
=fx
->TimingMode
;
6141 myfx
->Duration
=fx
->Duration
;
6142 myfx
->Target
= FX_TARGET_PRESET
;
6143 myfx
->CasterID
= fx
->CasterID
;
6144 ret
= target
->fxqueue
.ApplyEffect(target
, myfx
, fx
->FirstApply
, 0);
6147 //newfx is a borrowed reference don't delete it
6152 // 0x11c MeleeHitModifier
6153 int fx_melee_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6155 if (0) printf( "fx_melee_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6156 STAT_MOD( IE_MELEETOHIT
);
6160 // 0x11d MeleeDamageModifier
6161 int fx_melee_damage_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6163 if (0) printf( "fx_melee_damage_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6164 STAT_MOD( IE_MELEEDAMAGE
);
6168 // 0x11e MissileDamageModifier
6169 int fx_missile_damage_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6171 if (0) printf( "fx_missile_damage_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6172 STAT_MOD( IE_MISSILEDAMAGE
);
6176 // 0x11f NoCircleState
6177 int fx_no_circle_state (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6179 if (0) printf( "fx_missile_damage_modifier (%2d)\n", fx
->Opcode
);
6180 STAT_SET( IE_NOCIRCLE
, 1 );
6184 // 0x120 FistHitModifier
6185 int fx_fist_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6187 if (0) printf( "fx_fist_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6188 STAT_MOD( IE_FISTHIT
);
6192 // 0x121 FistDamageModifier
6193 int fx_fist_damage_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6195 if (0) printf( "fx_fist_damage_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6196 STAT_MOD( IE_FISTDAMAGE
);
6199 //0x122 TitleModifier
6200 int fx_title_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6202 if (0) printf( "fx_fist_damage_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6203 if (fx
->Parameter2
) {
6204 STAT_SET( IE_TITLE2
, fx
->Parameter1
);
6206 STAT_SET( IE_TITLE1
, fx
->Parameter1
);
6210 //0x123 DisableOverlay
6211 //FIXME: which overlay is disabled?
6212 //if one of the overlays marked by sanctuary, then
6213 //make the bit correspond to it
6214 int fx_disable_overlay_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6216 if (0) printf( "fx_disable_overlay_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6217 STAT_SET( IE_DISABLEOVERLAY
, fx
->Parameter1
);
6220 //0x124 Protection:Backstab (bg2)
6221 //0x11f Protection:Backstab (how, iwd2)
6222 //3 different games, 3 different methods of flagging this
6223 int fx_no_backstab_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6225 if (0) printf( "fx_no_backstab_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6227 STAT_SET( IE_DISABLEBACKSTAB
, fx
->Parameter1
);
6229 EXTSTATE_SET(EXTSTATE_NO_BACKSTAB
);
6231 target
->SetSpellState(SS_NOBACKSTAB
);
6234 //0x125 OffscreenAIModifier
6235 int fx_offscreenai_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6237 if (0) printf( "fx_offscreenai_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6238 STAT_SET( IE_ENABLEOFFSCREENAI
, fx
->Parameter1
);
6242 //0x126 ExistanceDelayModifier
6243 int fx_existance_delay_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6245 if (0) printf( "fx_existance_delay_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6246 STAT_SET( IE_EXISTANCEDELAY
, fx
->Parameter1
);
6249 //0x127 DisableChunk
6250 int fx_disable_chunk_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6252 if (0) printf( "fx_disable_chunk_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6253 STAT_SET( IE_DISABLECHUNKING
, fx
->Parameter1
);
6257 //This is done differently in the original engine, and THIS may not even work
6258 //0x128 Protection:Animation
6259 int fx_protection_from_animation (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6261 if (0) printf( "fx_protection_from_animation (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6262 //remove vvc from actor if active
6263 target
->RemoveVVCell(fx
->Resource
, false);
6268 //0x129 Protection:Turn
6269 int fx_protection_from_turn (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6271 if (0) printf( "fx_non_interruptible_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6272 STAT_SET( IE_NOTURNABLE
, fx
->Parameter1
);
6276 //runs a predetermined script in cutscene mode
6277 int fx_cutscene2 (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
6282 if (0) printf( "fx_cutscene2 (%2d): Type: %d\n", fx
->Opcode
, fx
->Parameter2
);
6283 if (core
->InCutSceneMode()) return FX_NOT_APPLIED
;
6284 game
= core
->GetGame();
6285 if (!game
) return FX_NOT_APPLIED
;
6287 game
->ClearPlaneLocations();
6288 for (int i
= 0; i
< game
->GetPartySize(false); i
++) {
6289 Actor
* act
= game
->GetPC( i
, false );
6290 GAMLocationEntry
*gle
= game
->GetPlaneLocationEntry(i
);
6292 gle
->Pos
= act
->Pos
;
6293 memcpy(gle
->AreaResRef
, act
->Area
, 9);
6297 core
->SetCutSceneMode(true);
6299 //GemRB enhancement: allow a custom resource
6300 if (fx
->Parameter2
) {
6301 strnlwrcpy(resref
,fx
->Resource
, 8);
6303 strnlwrcpy(resref
,"cut250a",8);
6306 GameScript
* gs
= new GameScript( resref
, game
);
6307 gs
->EvaluateAllBlocks();
6309 return FX_NOT_APPLIED
;
6311 //0x12b ChaosShieldModifier
6312 int fx_chaos_shield_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6314 if (0) printf( "fx_chaos_shield_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6315 STAT_ADD( IE_CHAOSSHIELD
, fx
->Parameter1
);
6316 if (fx
->Parameter2
) {
6317 target
->AddPortraitIcon(PI_CSHIELD
); //162
6319 target
->AddPortraitIcon(PI_CSHIELD2
); //163
6324 int fx_npc_bump (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6326 if (0) printf( "fx_npc_bump (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6327 //unknown effect, but known stat position
6328 STAT_MOD( IE_NPCBUMP
);
6331 //0x12d CriticalHitModifier
6332 int fx_critical_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6334 if (0) printf( "fx_critical_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6335 STAT_MOD( IE_CRITICALHITBONUS
);
6338 // 0x12e CanUseAnyItem
6339 int fx_can_use_any_item_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6341 if (0) printf( "fx_can_use_any_item_modifier (%2d): Value: %d\n", fx
->Opcode
, fx
->Parameter2
);
6343 STAT_SET( IE_CANUSEANYITEM
, fx
->Parameter2
);
6347 // 0x12f AlwaysBackstab
6348 int fx_always_backstab_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6350 if (0) printf( "fx_always_backstab_modifier (%2d): Value: %d\n", fx
->Opcode
, fx
->Parameter2
);
6352 STAT_SET( IE_ALWAYSBACKSTAB
, fx
->Parameter2
);
6356 // 0x130 MassRaiseDead
6357 int fx_mass_raise_dead (Scriptable
* Owner
, Actor
* /*target*/, Effect
* fx
)
6359 if (0) printf( "fx_mass_raise_dead (%2d)\n", fx
->Opcode
);
6361 Game
*game
=core
->GetGame();
6363 int i
=game
->GetPartySize(false);
6364 Point
p(fx
->PosX
,fx
->PosY
);
6366 Actor
*actor
=game
->GetPC(i
,false);
6367 Resurrect(Owner
, actor
, fx
, p
);
6369 return FX_NOT_APPLIED
;
6372 // 0x131 OffhandHitModifier
6373 int fx_left_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6375 if (0) printf( "fx_left_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6377 STAT_MOD( IE_HITBONUSLEFT
);
6381 // 0x132 RightHitModifier
6382 int fx_right_to_hit_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6384 if (0) printf( "fx_right_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6386 STAT_MOD( IE_HITBONUSRIGHT
);
6390 // 0x133 Reveal:Tracks
6391 int fx_reveal_tracks (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6393 if (0) printf( "fx_reveal_tracks (%2d): Distance: %d\n", fx
->Opcode
, fx
->Parameter1
);
6394 Map
*map
= target
->GetCurrentArea();
6395 if (!map
) return FX_APPLIED
;
6396 if (!fx
->Parameter2
) {
6398 //write tracks.2da entry
6399 if (map
->DisplayTrackString(target
)) {
6400 return FX_NOT_APPLIED
;
6403 GameControl
*gc
= core
->GetGameControl();
6405 //highlight all living creatures (not in party, but within range)
6406 gc
->SetTracker(target
, fx
->Parameter1
);
6411 // 0x134 Protection:Tracking
6412 int fx_protection_from_tracking (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6414 if (0) printf( "fx_protection_from_tracking (%2d): Mod: %d, Type: %d\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
);
6416 STAT_MOD( IE_NOTRACKING
); //highlight creature???
6419 // 0x135 ModifyLocalVariable
6420 int fx_modify_local_variable (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6422 //convert it to internal variable format
6423 if (!fx
->IsVariable
) {
6424 char *poi
= fx
->Resource
+8;
6425 memmove(poi
, fx
->Resource2
, 8);
6427 memmove(poi
, fx
->Resource3
, 8);
6429 memmove(poi
, fx
->Resource4
, 8);
6432 if (0) printf( "fx_modify_local_variable (%2d): %s, Mod: %d\n", fx
->Opcode
, fx
->Resource
, fx
->Parameter2
);
6433 if (fx
->Parameter2
) {
6435 //use resource memory area as variable name
6436 target
->locals
->Lookup(fx
->Resource
, var
);
6437 target
->locals
->SetAt(fx
->Resource
, var
+fx
->Parameter1
);
6439 target
->locals
->SetAt(fx
->Resource
, fx
->Parameter1
);
6441 return FX_NOT_APPLIED
;
6444 // 0x136 TimelessState
6445 int fx_timeless_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6447 if (0) printf( "fx_timeless_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter2
);
6448 STAT_SET(IE_DISABLETIMESTOP
, fx
->Parameter2
);
6452 //0x137 GenerateWish
6453 #define WISHCOUNT 25
6454 static int wishlevels
[WISHCOUNT
]={10,10,10,10,0,10,0,15,0,0,0,0,0,0,15,0,0,
6455 17,9,17,17,9,9,9,0};
6457 int fx_generate_wish (Scriptable
* Owner
, Actor
* target
, Effect
* fx
)
6461 if (0) printf( "fx_generate_wish (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter2
);
6462 int tmp
= core
->Roll(1,WISHCOUNT
,0);
6463 sprintf(spl
,"SPWISH%02d",tmp
);
6464 core
->ApplySpell(spl
, target
, Owner
, wishlevels
[tmp
-1]);
6465 return FX_NOT_APPLIED
;
6467 //0x138 //see fx_crash, this effect is not fully enabled in original bg2/tob
6468 int fx_immunity_sequester (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6470 if (0) printf( "fx_immunity_sequester (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter2
);
6471 //this effect is supposed to provide immunity against sequester (maze/etc?)
6472 STAT_SET(IE_NOSEQUESTER
, fx
->Parameter2
);
6476 //0x139 //HLA generic effect
6477 //0x13a StoneSkin2Modifier
6478 int fx_golem_stoneskin_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6480 if (0) printf( "fx_golem_stoneskin_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter1
);
6481 if (!fx
->Parameter1
) {
6482 return FX_NOT_APPLIED
;
6484 //dead actors lose this effect
6485 if (STATE_GET( STATE_DEAD
) ) {
6486 return FX_NOT_APPLIED
;
6489 STAT_SET(IE_STONESKINSGOLEM
, fx
->Parameter1
);
6490 SetGradient(target
, 14);
6494 // 0x13b AvatarRemovalModifier (also 0x104 iwd)
6495 int fx_avatar_removal_modifier (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6497 if (0) printf( "fx_avatar_removal_modifier (%2d): Mod: %d\n", fx
->Opcode
, fx
->Parameter2
);
6498 STAT_SET(IE_AVATARREMOVAL
, fx
->Parameter2
);
6502 // 0x13c MagicalRest (also 0x124 iwd)
6503 int fx_magical_rest (Scriptable
* /*Owner*/, Actor
* target
, Effect
* fx
)
6505 if (0) printf( "fx_magical_rest (%2d)\n", fx
->Opcode
);
6506 //instant, full rest
6508 target
->fxqueue
.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref
, PI_FATIGUE
);
6509 return FX_NOT_APPLIED
;
6512 // 0x13d ImprovedHaste (See 0x10 Haste)
6514 int fx_unknown (Scriptable
* /*Owner*/, Actor
* /*target*/, Effect
* fx
)
6516 printf( "fx_unknown (%2d): P1: %d P2: %d ResRef: %s\n", fx
->Opcode
, fx
->Parameter1
, fx
->Parameter2
, fx
->Resource
);
6517 return FX_NOT_APPLIED
;
6520 #include "plugindef.h"
6522 GEMRB_PLUGIN(0x1AAA040A, "Effect opcodes for core games")
6523 PLUGIN_INITIALIZER(RegisterCoreOpcodes
)
6524 PLUGIN_CLEANUP(Cleanup
)