Split GameScript into subdirectory.
[gemrb.git] / gemrb / plugins / FXOpcodes / FXOpcodes.cpp
blob982ef4b138f42c7c2cf601286e94f2cc44a29da0
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"
23 #include "overlays.h"
24 #include "strrefs.h"
25 #include "win32def.h"
27 #include "Audio.h"
28 #include "DisplayMessage.h"
29 #include "EffectQueue.h"
30 #include "Game.h"
31 #include "GameData.h"
32 #include "Interface.h"
33 #include "Projectile.h" //needs for clearair
34 #include "TileMap.h" //needs for knock!
35 #include "damages.h"
36 #include "GameScript/GSUtils.h" //needs for MoveBetweenAreasCore
37 #include "GUI/GameControl.h"
38 #include "Scriptable/Actor.h"
40 //FIXME: find a way to handle portrait icons better
41 #define PI_CONFUSED 3
42 #define PI_BERSERK 4
43 #define PI_POISONED 6
44 #define PI_HELD 13
45 #define PI_SLEEP 14
46 #define PI_BLESS 17
47 #define PI_PANIC 36
48 #define PI_HASTED 38
49 #define PI_FATIGUE 39
50 #define PI_SLOWED 41
51 #define PI_HOPELESS 44
52 #define PI_LEVELDRAIN 53
53 #define PI_FEEBLEMIND 54
54 #define PI_STUN 55
55 #define PI_AID 57
56 #define PI_HOLY 59
57 #define PI_BOUNCE 65
58 #define PI_BOUNCE2 67
60 #define PI_BLOODRAGE 76 //iwd2
61 #define PI_MAZE 78
62 #define PI_PRISON 79
63 #define PI_STONESKIN 80
64 #define PI_DEAFNESS 83 //iwd2
65 #define PI_SEQUENCER 92
66 #define PI_BLUR 109
67 #define PI_IMPROVEDHASTE 110
68 #define PI_SPELLTRAP 117
69 #define PI_CSHIELD 162
70 #define PI_CSHIELD2 163
72 static ieResRef *casting_glows = NULL;
73 static int cgcount = -1;
74 static ieResRef *spell_hits = NULL;
75 static bool enhanced_effects = false;
76 static int shcount = -1;
77 static int *spell_abilities = NULL;
78 static ieDword splabcount = 0;
79 static int *polymorph_stats = NULL;
80 static int polystatcount = 0;
82 //the original engine stores the colors in sprklclr.2da in a different order
84 #define SPARK_COUNT 13
86 static int spark_color_indices[SPARK_COUNT]={12,5,0,6,1,8,2,7,9,3,4,10,11};
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 //unknown
275 //b5 //unknown
276 //b6 //unknown
277 //b7 //unknown
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 //f8 melee effect (general effect?)
345 //f9 ranged effect (general effect?)
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
408 //138 see fx_crash
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 { "ApplyEffectItemType", fx_generic_effect, -1 }, //apply effect when itemtype is equipped
435 { "ApplyEffectRepeat", fx_apply_effect_repeat, -1 },
436 { "CutScene2", fx_cutscene2, -1 },
437 { "AttackSpeedModifier", fx_attackspeed_modifier, -1 },
438 { "AttacksPerRoundModifier", fx_attacks_per_round_modifier, -1 },
439 { "AuraCleansingModifier", fx_auracleansing_modifier, -1 },
440 { "AvatarRemoval", fx_avatar_removal, -1 }, //unknown
441 { "AvatarRemovalModifier", fx_avatar_removal_modifier, -1 },
442 { "BackstabModifier", fx_backstab_modifier, -1 },
443 { "BerserkStage1Modifier", fx_berserkstage1_modifier, -1},
444 { "BerserkStage2Modifier", fx_berserkstage2_modifier, -1},
445 { "BlessNonCumulative", fx_set_bless_state, -1 },
446 { "Bounce:School", fx_bounce_school, -1 },
447 { "Bounce:SchoolDec", fx_bounce_school_dec, -1 },
448 { "Bounce:SecondaryType", fx_bounce_secondary_type, -1 },
449 { "Bounce:SecondaryTypeDec", fx_bounce_secondary_type_dec, -1 },
450 { "Bounce:Spell", fx_bounce_spell, -1 },
451 { "Bounce:SpellDec", fx_bounce_spell_dec, -1 },
452 { "Bounce:SpellLevel", fx_bounce_spelllevel, -1},
453 { "Bounce:SpellLevelDec", fx_bounce_spelllevel_dec, -1},
454 { "Bounce:Opcode", fx_bounce_opcode, -1 },
455 { "Bounce:Projectile", fx_bounce_projectile, -1 },
456 { "CantUseItem", fx_generic_effect, -1 },
457 { "CantUseItemType", fx_generic_effect, -1 },
458 { "CanUseAnyItem", fx_can_use_any_item_modifier, -1 },
459 { "CastFromList", fx_select_spell, -1 },
460 { "CastingGlow", fx_casting_glow, -1 },
461 { "CastingGlow2", fx_casting_glow, -1 }, //used in iwd
462 { "CastingLevelModifier", fx_castinglevel_modifier, -1 },
463 { "CastingSpeedModifier", fx_castingspeed_modifier, -1 },
464 { "CastSpellOnCondition", fx_cast_spell_on_condition, -1 },
465 { "ChangeBardSong", fx_generic_effect, -1 },
466 { "ChangeName", fx_change_name, -1 },
467 { "ChantBadNonCumulative", fx_set_chantbad_state, -1 },
468 { "ChantNonCumulative", fx_set_chant_state, -1 },
469 { "ChaosShieldModifier", fx_chaos_shield_modifier, -1 },
470 { "CharismaModifier", fx_charisma_modifier, -1 },
471 { "CheckForBerserkModifier", fx_checkforberserk_modifier, -1},
472 { "ColdResistanceModifier", fx_cold_resistance_modifier, -1 },
473 { "Color:BriefRGB", fx_brief_rgb, -1},
474 { "Color:GlowRGB", fx_glow_rgb, -1},
475 { "Color:DarkenRGB", fx_darken_rgb, -1},
476 { "Color:SetPalette", fx_set_color_gradient, -1 },
477 { "Color:SetRGB", fx_set_color_rgb, -1 },
478 { "Color:SetRGBGlobal", fx_set_color_rgb_global, -1 }, //08
479 { "Color:PulseRGB", fx_set_color_pulse_rgb, -1 }, //9
480 { "Color:PulseRGBGlobal", fx_set_color_pulse_rgb_global, -1 }, //9
481 { "ConstitutionModifier", fx_constitution_modifier, -1 },
482 { "ControlCreature", fx_set_charmed_state, -1 }, //0xf1 same as charm
483 { "CreateContingency", fx_create_contingency, -1 },
484 { "CriticalHitModifier", fx_critical_hit_modifier, -1 },
485 { "CrushingResistanceModifier", fx_crushing_resistance_modifier, -1 },
486 { "Cure:Berserk", fx_cure_berserk_state, -1 },
487 { "Cure:Blind", fx_cure_blind_state, -1 },
488 { "Cure:CasterHold", fx_unpause_caster, -1 },
489 { "Cure:Confusion", fx_cure_confused_state, -1 },
490 { "Cure:Deafness", fx_cure_deaf_state, -1 },
491 { "Cure:Death", fx_cure_dead_state, -1 },
492 { "Cure:Defrost", fx_cure_frozen_state, -1 },
493 { "Cure:Disease", fx_cure_diseased_state, -1 },
494 { "Cure:Feeblemind", fx_cure_feebleminded_state, -1 },
495 { "Cure:Hold", fx_cure_hold_state, -1 },
496 { "Cure:Imprisonment", fx_freedom, -1 },
497 { "Cure:Infravision", fx_cure_infravision_state, -1 },
498 { "Cure:Intoxication", fx_cure_intoxication, -1 }, //0xa4 (iwd2 has this working)
499 { "Cure:Invisible", fx_cure_invisible_state, -1 }, //0x2f
500 { "Cure:Invisible2", fx_cure_invisible_state, -1 }, //0x74
501 //{ "Cure:ImprovedInvisible", fx_cure_improved_invisible_state, -1 },
502 { "Cure:LevelDrain", fx_cure_leveldrain, -1}, //restoration
503 { "Cure:Nondetection", fx_cure_nondetection_state, -1 },
504 { "Cure:Panic", fx_cure_panic_state, -1 },
505 { "Cure:Petrification", fx_cure_petrified_state, -1 },
506 { "Cure:Poison", fx_cure_poisoned_state, -1 },
507 { "Cure:Sanctuary", fx_cure_sanctuary_state, -1 },
508 { "Cure:Silence", fx_cure_silenced_state, -1 },
509 { "Cure:Sleep", fx_cure_sleep_state, -1 },
510 { "Cure:Stun", fx_cure_stun_state, -1 },
511 { "CurrentHPModifier", fx_current_hp_modifier, -1 },
512 { "Damage", fx_damage, -1 },
513 { "DamageAnimation", fx_damage_animation, -1 },
514 { "DamageBonusModifier", fx_damage_bonus_modifier, -1 },
515 { "DamageLuckModifier", fx_damageluck_modifier, -1 },
516 { "DamageVsCreature", fx_generic_effect, -1 },
517 { "Death", fx_death, -1 },
518 { "Death2", fx_death, -1 }, //(iwd2 effect)
519 { "Death3", fx_death, -1 }, //(iwd2 effect too, Banish)
520 { "DetectAlignment", fx_detect_alignment, -1 },
521 { "DetectIllusionsModifier", fx_detect_illusion_modifier, -1 },
522 { "DexterityModifier", fx_dexterity_modifier, -1 },
523 { "DimensionDoor", fx_dimension_door, -1 },
524 { "DisableButton", fx_disable_button, -1 }, //sets disable button flag
525 { "DisableChunk", fx_disable_chunk_modifier, -1 },
526 { "DisableOverlay", fx_disable_overlay_modifier, -1 },
527 { "DisableCasting", fx_disable_spellcasting, -1 },
528 { "Disintegrate", fx_disintegrate, -1 },
529 { "DispelEffects", fx_dispel_effects, -1 },
530 { "DispelSchool", fx_dispel_school, -1 },
531 { "DispelSchoolOne", fx_dispel_school_one, -1 },
532 { "DispelSecondaryType", fx_dispel_secondary_type, -1 },
533 { "DispelSecondaryTypeOne", fx_dispel_secondary_type_one, -1 },
534 { "DisplayString", fx_display_string, -1 },
535 { "Dither", fx_dither, -1 },
536 { "DontJumpModifier", fx_dontjump_modifier, -1 },
537 { "DrainItems", fx_drain_items, -1 },
538 { "DrainSpells", fx_drain_spells, -1 },
539 { "DropWeapon", fx_drop_weapon, -1 },
540 { "ElectricityResistanceModifier", fx_electricity_resistance_modifier, -1 },
541 { "ExistanceDelayModifier", fx_existance_delay_modifier , -1 }, //unknown
542 { "ExperienceModifier", fx_experience_modifier, -1 },
543 { "ExploreModifier", fx_explore_modifier, -1 },
544 { "FamiliarBond", fx_familiar_constitution_loss, -1 },
545 { "FamiliarMarker", fx_familiar_marker, -1},
546 { "Farsee", fx_farsee, -1},
547 { "FatigueModifier", fx_fatigue_modifier, -1 },
548 { "FindFamiliar", fx_find_familiar, -1 },
549 { "FindTraps", fx_find_traps, -1 },
550 { "FindTrapsModifier", fx_find_traps_modifier, -1 },
551 { "FireResistanceModifier", fx_fire_resistance_modifier, -1 },
552 { "FistDamageModifier", fx_fist_damage_modifier, -1 },
553 { "FistHitModifier", fx_fist_to_hit_modifier, -1 },
554 { "ForceSurgeModifier", fx_force_surge_modifier, -1 },
555 { "ForceVisible", fx_force_visible, -1 }, //not invisible but improved invisible
556 { "FreeAction", fx_cure_slow_state, -1},
557 { "GenerateWish", fx_generate_wish, -1},
558 { "GoldModifier", fx_gold_modifier, -1 },
559 { "HideInShadowsModifier", fx_hide_in_shadows_modifier, -1},
560 { "HLA", fx_generic_effect, -1},
561 { "HolyNonCumulative", fx_set_holy_state, -1 },
562 { "Icon:Disable", fx_disable_portrait_icon, -1 },
563 { "Icon:Display", fx_display_portrait_icon, -1 },
564 { "Icon:Remove", fx_remove_portrait_icon, -1 },
565 { "Identify", fx_identify, -1 },
566 { "IgnoreDialogPause", fx_ignore_dialogpause_modifier, -1 },
567 { "IntelligenceModifier", fx_intelligence_modifier, -1 },
568 { "IntoxicationModifier", fx_intoxication_modifier, -1 },
569 { "InvisibleDetection", fx_see_invisible_modifier, -1 },
570 { "Item:CreateDays", fx_create_item_days, -1 },
571 { "Item:CreateInSlot", fx_create_item_in_slot, -1 },
572 { "Item:CreateInventory", fx_create_inventory_item, -1 },
573 { "Item:CreateMagic", fx_create_magic_item, -1 },
574 { "Item:Equip", fx_equip_item, -1 }, //71
575 { "Item:Remove", fx_remove_item, -1 }, //70
576 { "Item:RemoveInventory", fx_remove_inventory_item, -1 },
577 { "KillCreatureType", fx_kill_creature_type, -1 },
578 { "LevelModifier", fx_level_modifier, -1 },
579 { "LevelDrainModifier", fx_leveldrain_modifier, -1 },
580 { "LoreModifier", fx_lore_modifier, -1 },
581 { "LuckModifier", fx_luck_modifier, -1 },
582 { "LuckCumulative", fx_luck_cumulative, -1 },
583 { "LuckNonCumulative", fx_luck_non_cumulative, -1 },
584 { "MagicalColdResistanceModifier", fx_magical_cold_resistance_modifier, -1 },
585 { "MagicalFireResistanceModifier", fx_magical_fire_resistance_modifier, -1 },
586 { "MagicalRest", fx_magical_rest, -1 },
587 { "MagicDamageResistanceModifier", fx_magic_damage_resistance_modifier, -1 },
588 { "MagicResistanceModifier", fx_magic_resistance_modifier, -1 },
589 { "MassRaiseDead", fx_mass_raise_dead, -1 },
590 { "MaximumHPModifier", fx_maximum_hp_modifier, -1 },
591 { "Maze", fx_maze, -1},
592 { "MeleeDamageModifier", fx_melee_damage_modifier, -1 },
593 { "MeleeHitModifier", fx_melee_to_hit_modifier, -1 },
594 { "MinimumHPModifier", fx_minimum_hp_modifier, -1 },
595 { "MiscastMagicModifier", fx_miscast_magic_modifier, -1 },
596 { "MissileDamageModifier", fx_missile_damage_modifier, -1 },
597 { "MissileHitModifier", fx_missile_to_hit_modifier, -1 },
598 { "MissilesResistanceModifier", fx_missiles_resistance_modifier, -1 },
599 { "MirrorImage", fx_mirror_image, -1 },
600 { "MirrorImageModifier", fx_mirror_image_modifier, -1 },
601 { "ModifyGlobalVariable", fx_modify_global_variable, -1 },
602 { "ModifyLocalVariable", fx_modify_local_variable, -1 },
603 { "MonsterSummoning", fx_monster_summoning, -1 },
604 { "MoraleBreakModifier", fx_morale_break_modifier, -1 },
605 { "MoraleModifier", fx_morale_modifier, -1 },
606 { "MovementRateModifier", fx_movement_modifier, -1 }, //fast (7e)
607 { "MovementRateModifier2", fx_movement_modifier, -1 },//slow (b0)
608 { "MovementRateModifier3", fx_movement_modifier, -1 },//forced (IWD - 10a)
609 { "MovementRateModifier4", fx_movement_modifier, -1 },//slow (IWD2 - 1b9)
610 { "MoveToArea", fx_move_to_area, -1 }, //0xba
611 { "NoCircleState", fx_no_circle_state, -1 },
612 { "NPCBump", fx_npc_bump, -1 },
613 { "OffscreenAIModifier", fx_offscreenai_modifier, -1 },
614 { "OffhandHitModifier", fx_left_to_hit_modifier, -1 },
615 { "OpenLocksModifier", fx_open_locks_modifier, -1 },
616 { "Overlay:Entangle", fx_set_entangle_state, -1 },
617 { "Overlay:Grease", fx_set_grease_state, -1 },
618 { "Overlay:MinorGlobe", fx_set_minorglobe_state, -1 },
619 { "Overlay:Sanctuary", fx_set_sanctuary_state, -1 },
620 { "Overlay:ShieldGlobe", fx_set_shieldglobe_state, -1 },
621 { "Overlay:Web", fx_set_web_state, -1 },
622 { "PauseTarget", fx_pause_target, -1 }, //also known as casterhold
623 { "PickPocketsModifier", fx_pick_pockets_modifier, -1 },
624 { "PiercingResistanceModifier", fx_piercing_resistance_modifier, -1 },
625 { "PlayMovie", fx_play_movie, -1 },
626 { "PlaySound", fx_playsound, -1 },
627 { "PlayVisualEffect", fx_play_visual_effect, -1 },
628 { "PoisonResistanceModifier", fx_poison_resistance_modifier, -1 },
629 { "Polymorph", fx_polymorph, -1},
630 { "PortraitChange", fx_portrait_change, -1 },
631 { "PowerWordKill", fx_power_word_kill, -1 },
632 { "PowerWordSleep", fx_power_word_sleep, -1 },
633 { "PowerWordStun", fx_power_word_stun, -1 },
634 { "PriestSpellSlotsModifier", fx_bonus_priest_spells, -1 },
635 { "Proficiency", fx_proficiency, -1 },
636 { "Protection:Animation", fx_generic_effect, -1 },
637 { "Protection:Backstab", fx_no_backstab_modifier, -1 },
638 { "Protection:Creature", fx_generic_effect, -1 },
639 { "Protection:Opcode", fx_protection_opcode, -1 },
640 { "Protection:Opcode2", fx_protection_opcode, -1 },
641 { "Protection:Projectile",fx_protection_from_projectile, -1},
642 { "Protection:School",fx_generic_effect,-1},//overlay?
643 { "Protection:SchoolDec",fx_protection_school_dec,-1},//overlay?
644 { "Protection:SecondaryType",fx_protection_secondary_type,-1},//overlay?
645 { "Protection:SecondaryTypeDec",fx_protection_secondary_type_dec,-1},//overlay?
646 { "Protection:Spell",fx_resist_spell,-1},//overlay?
647 { "Protection:SpellDec",fx_resist_spell_dec,-1},//overlay?
648 { "Protection:SpellLevel",fx_protection_spelllevel,-1},//overlay?
649 { "Protection:SpellLevelDec",fx_protection_spelllevel_dec,-1},//overlay?
650 { "Protection:String", fx_generic_effect, -1 },
651 { "Protection:Tracking", fx_protection_from_tracking, -1 },
652 { "Protection:Turn", fx_protection_from_turn, -1},
653 { "Protection:Weapons", fx_immune_to_weapon, -1},
654 { "PuppetMarker", fx_puppet_marker, -1},
655 { "ProjectImage", fx_puppet_master, -1},
656 { "Reveal:Area", fx_reveal_area, -1 },
657 { "Reveal:Creatures", fx_reveal_creatures, -1 },
658 { "Reveal:Magic", fx_reveal_magic, -1 },
659 { "Reveal:Tracks", fx_reveal_tracks, -1 },
660 { "RemoveCurse", fx_remove_curse, -1 },
661 { "RemoveImmunity", fx_remove_immunity, -1 },
662 { "RemoveMapNote", fx_remove_map_note, -1 },
663 { "RemoveProjectile", fx_remove_projectile, -1 }, //removes effects from actor and area
664 { "RenableButton", fx_renable_button, -1 }, //removes disable button flag
665 { "RemoveCreature", fx_remove_creature, -1 },
666 { "ReplaceCreature", fx_replace_creature, -1 },
667 { "ReputationModifier", fx_reputation_modifier, -1 },
668 { "RestoreSpells", fx_restore_spell_level, -1 },
669 { "RightHitModifier", fx_right_to_hit_modifier, -1 },
670 { "SaveVsBreathModifier", fx_save_vs_breath_modifier, -1 },
671 { "SaveVsDeathModifier", fx_save_vs_death_modifier, -1 },
672 { "SaveVsPolyModifier", fx_save_vs_poly_modifier, -1 },
673 { "SaveVsSpellsModifier", fx_save_vs_spell_modifier, -1 },
674 { "SaveVsWandsModifier", fx_save_vs_wands_modifier, -1 },
675 { "ScreenShake", fx_screenshake, -1 },
676 { "ScriptingState", fx_scripting_state, -1 },
677 { "Sequencer:Activate", fx_activate_spell_sequencer, -1 },
678 { "Sequencer:Create", fx_create_spell_sequencer, -1 },
679 { "Sequencer:Store", fx_store_spell_sequencer, -1 },
680 { "SetAIScript", fx_set_ai_script, -1 },
681 { "SetMapNote", fx_set_map_note, -1 },
682 { "SetMeleeEffect", fx_generic_effect, -1 },
683 { "SetRangedEffect", fx_generic_effect, -1 },
684 { "SetTrap", fx_set_area_effect, -1 },
685 { "SetTrapsModifier", fx_set_traps_modifier, -1 },
686 { "SexModifier", fx_sex_modifier, -1 },
687 { "SlashingResistanceModifier", fx_slashing_resistance_modifier, -1 },
688 { "SlowPoisonDamageRate", fx_generic_effect, -1 }, //slow poison effect
689 { "Sparkle", fx_sparkle, -1 },
690 { "SpellDurationModifier", fx_spell_duration_modifier, -1 },
691 { "Spell:Add", fx_add_innate, -1 },
692 { "Spell:Cast", fx_cast_spell, -1 },
693 { "Spell:CastPoint", fx_cast_spell_point, -1 },
694 { "Spell:Learn", fx_learn_spell, -1 },
695 { "Spell:Remove", fx_remove_spell, -1 },
696 { "Spelltrap",fx_spelltrap , -1 }, //overlay: spmagglo
697 { "State:Berserk", fx_set_berserk_state, -1 },
698 { "State:Blind", fx_set_blind_state, -1 },
699 { "State:Blur", fx_set_blur_state, -1 },
700 { "State:Charmed", fx_set_charmed_state, -1 }, //0x05
701 { "State:Confused", fx_set_confused_state, -1 },
702 { "State:Deafness", fx_set_deaf_state, -1 },
703 { "State:DeafnessIWD2", fx_set_deaf_state_iwd2, -1 }, //this is a modified version
704 { "State:Diseased", fx_set_diseased_state, -1 },
705 { "State:Feeblemind", fx_set_feebleminded_state, -1 },
706 { "State:Hasted", fx_set_hasted_state, -1 },
707 { "State:Haste2", fx_set_hasted_state, -1 },
708 { "State:Hold", fx_hold_creature, -1 }, //175 (doesn't work in original iwd2)
709 { "State:Hold2", fx_hold_creature, -1 },//185 (doesn't work in original iwd2)
710 { "State:Hold3", fx_hold_creature, -1 },//109 iwd2
711 { "State:HoldNoIcon", fx_hold_creature_no_icon, -1 }, //109
712 { "State:HoldNoIcon2", fx_hold_creature_no_icon, -1 }, //0xfb (iwd/iwd2)
713 { "State:HoldNoIcon3", fx_hold_creature_no_icon, -1 }, //0x1a8 (iwd2)
714 { "State:Imprisonment", fx_imprisonment, -1 },
715 { "State:Infravision", fx_set_infravision_state, -1 },
716 { "State:Invisible", fx_set_invisible_state, -1 }, //both invis or improved invis
717 { "State:Nondetection", fx_set_nondetection_state, -1 },
718 { "State:Panic", fx_set_panic_state, -1 },
719 { "State:Petrification", fx_set_petrified_state, -1 },
720 { "State:Poisoned", fx_set_poisoned_state, -1 },
721 { "State:Regenerating", fx_set_regenerating_state, -1 },
722 { "State:Silenced", fx_set_silenced_state, -1 },
723 { "State:Helpless", fx_set_unconscious_state, -1 },
724 { "State:Sleep", fx_set_unconscious_state, -1},
725 { "State:Slowed", fx_set_slowed_state, -1 },
726 { "State:Stun", fx_set_stun_state, -1 },
727 { "StealthModifier", fx_stealth_modifier, -1 },
728 { "StoneSkinModifier", fx_stoneskin_modifier, -1 },
729 { "StoneSkin2Modifier", fx_golem_stoneskin_modifier, -1 },
730 { "StrengthModifier", fx_strength_modifier, -1 },
731 { "StrengthBonusModifier", fx_strength_bonus_modifier, -1 },
732 { "SummonCreature", fx_summon_creature, -1 },
733 { "RandomTeleport", fx_teleport_field, -1 },
734 { "TeleportToTarget", fx_teleport_to_target, -1 },
735 { "TimelessState", fx_timeless_modifier, -1 },
736 { "Timestop", fx_timestop, -1},
737 { "TitleModifier", fx_title_modifier, -1 },
738 { "ToHitModifier", fx_to_hit_modifier, -1 },
739 { "ToHitBonusModifier", fx_to_hit_bonus_modifier, -1 },
740 { "ToHitVsCreature", fx_generic_effect, -1 },
741 { "TrackingModifier", fx_tracking_modifier, -1 },
742 { "TransparencyModifier", fx_transparency_modifier, -1 },
743 { "Unknown", fx_unknown, -1},
744 { "Unlock", fx_knock, -1 }, //open doors/containers
745 { "UnsummonCreature", fx_unsummon_creature, -1 },
746 { "Variable:StoreLocalVariable", fx_local_variable, -1 },
747 { "VisualAnimationEffect", fx_visual_animation_effect, -1 }, //unknown
748 { "VisualRangeModifier", fx_visual_range_modifier, -1 },
749 { "VisualSpellHit", fx_visual_spell_hit, -1 },
750 { "WildSurgeModifier", fx_wild_surge_modifier, -1 },
751 { "WingBuffet", fx_wing_buffet, -1 },
752 { "WisdomModifier", fx_wisdom_modifier, -1 },
753 { "WizardSpellSlotsModifier", fx_bonus_wizard_spells, -1 },
754 { NULL, NULL, 0 },
757 static void Cleanup()
759 core->FreeResRefTable(casting_glows, cgcount);
760 core->FreeResRefTable(spell_hits, shcount);
761 if(spell_abilities) free(spell_abilities);
762 spell_abilities=NULL;
763 if(polymorph_stats) free(polymorph_stats);
764 polymorph_stats=NULL;
767 void RegisterCoreOpcodes()
769 core->RegisterOpcodes( sizeof( effectnames ) / sizeof( EffectRef ) - 1, effectnames );
770 enhanced_effects=!!core->HasFeature(GF_ENHANCED_EFFECTS);
771 default_spell_hit.SequenceFlags|=IE_VVC_BAM;
775 static inline void SetGradient(Actor *target, ieDword gradient)
777 gradient |= (gradient <<16);
778 gradient |= (gradient <<8);
779 for(int i=0;i<7;i++) {
780 STAT_SET(IE_COLORS+i, gradient);
784 static inline void HandleBonus(Actor *target, int stat, int mod, int mode)
786 if (mode==FX_DURATION_INSTANT_PERMANENT) {
787 if (target->IsReverseToHit()) {
788 BASE_SUB( stat, mod );
789 } else {
790 BASE_ADD( stat, mod );
792 return;
794 if (target->IsReverseToHit()) {
795 STAT_SUB( stat, mod );
796 } else {
797 STAT_ADD( stat, mod );
801 //whoseeswho:
802 #define ENEMY_SEES_ORIGIN 1
803 #define ORIGIN_SEES_ENEMY 2
805 inline Actor *GetNearestEnemyOf(Map *map, Actor *origin, int whoseeswho)
807 //determining the allegiance of the origin
808 int type = GetGroup(origin);
810 //neutral has no enemies
811 if (type==2) {
812 return NULL;
815 Targets *tgts = new Targets();
817 int i = map->GetActorCount(true);
818 Actor *ac;
819 while (i--) {
820 ac=map->GetActor(i,true);
821 int distance = Distance(ac, origin);
822 if (whoseeswho&ENEMY_SEES_ORIGIN) {
823 if (!CanSee(ac, origin, true, GA_NO_DEAD)) {
824 continue;
827 if (whoseeswho&ORIGIN_SEES_ENEMY) {
828 if (!CanSee(ac, origin, true, GA_NO_DEAD)) {
829 continue;
833 if (type) { //origin is PC
834 if (ac->GetStat(IE_EA) >= EA_EVILCUTOFF) {
835 tgts->AddTarget(ac, distance, GA_NO_DEAD);
838 else {
839 if (ac->GetStat(IE_EA) <= EA_GOODCUTOFF) {
840 tgts->AddTarget(ac, distance, GA_NO_DEAD);
844 ac = (Actor *) tgts->GetTarget(0, ST_ACTOR);
845 delete tgts;
846 return ac;
849 inline Scriptable *GetCaster(Scriptable *Owner, Effect *fx) {
850 if (fx->FirstApply) {
851 fx->CasterID = Owner ? Owner->GetGlobalID() : 0;
852 return Owner;
853 } else {
854 return core->GetGame()->GetActorByGlobalID(fx->CasterID);
856 return NULL;
859 // handles the percentage damage spread over time by converting it to absolute damage
860 inline void HandlePercentageDamage(Effect *fx, Actor *target) {
861 if (fx->Parameter2 == RPD_PERCENT && fx->FirstApply) {
862 // distribute the damage to one second intervals
863 int seconds = (fx->Duration - core->GetGame()->GameTime) / AI_UPDATE_TIME;
864 fx->Parameter1 = target->GetStat(IE_MAXHITPOINTS) * fx->Parameter1 / 100 / seconds;
867 // Effect opcodes
869 // 0x00 ACVsDamageTypeModifier
870 int fx_ac_vs_damage_type_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
872 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 );
873 //check level was pulled outside as a common functionality
874 //CHECK_LEVEL();
876 // it is a bitmask
877 int type = fx->Parameter2;
878 if (type == 0) {
879 HandleBonus(target, IE_ARMORCLASS, fx->Parameter1, fx->TimingMode);
880 return FX_PERMANENT;
883 //convert to signed so -1 doesn't turn to an astronomical number
884 if (type == 16) {
885 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
886 if ((signed)BASE_GET( IE_ARMORCLASS) > (signed)fx->Parameter1) {
887 BASE_SET( IE_ARMORCLASS, fx->Parameter1 );
889 } else {
890 if ((signed)STAT_GET( IE_ARMORCLASS) > (signed)fx->Parameter1) {
891 STAT_SET( IE_ARMORCLASS, fx->Parameter1 );
894 return FX_INSERT;
897 //the original engine did work with the combination of these bits
898 //but since it crashed, we are not bound to the same rules
899 if (type & 1) {
900 HandleBonus(target, IE_ACCRUSHINGMOD, fx->Parameter1, fx->TimingMode);
902 if (type & 2) {
903 HandleBonus(target, IE_ACMISSILEMOD, fx->Parameter1, fx->TimingMode);
905 if (type & 4) {
906 HandleBonus(target, IE_ACPIERCINGMOD, fx->Parameter1, fx->TimingMode);
908 if (type & 8) {
909 HandleBonus(target, IE_ACSLASHINGMOD, fx->Parameter1, fx->TimingMode);
912 return FX_PERMANENT;
915 // 0x01 AttacksPerRoundModifier
916 int fx_attacks_per_round_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
918 if (0) printf( "fx_attacks_per_round_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
919 int tmp = (signed) fx->Parameter1;
920 if (fx->Parameter2!=2) {
921 if (tmp>10) tmp=10;
922 else if (tmp<-10) tmp=-10;
923 tmp <<= 1;
924 if (tmp>10) tmp-=11;
925 else if (tmp<-10) tmp+=11;
928 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
929 BASE_MOD_VAR(IE_NUMBEROFATTACKS, tmp);
930 } else {
931 STAT_MOD_VAR(IE_NUMBEROFATTACKS, tmp);
933 return FX_PERMANENT;
936 // 0x02 Cure:Sleep (Awaken)
937 // this effect clears the STATE_SLEEP (1) bit, but clearing it alone wouldn't remove the
938 // unconscious effect, which is combined with STATE_HELPLESS (0x20+1)
939 static EffectRef fx_set_sleep_state_ref={"State:Helpless",NULL,-1};
940 //this reference is used by many other effects
941 static EffectRef fx_display_portrait_icon_ref={"Icon:Display",NULL,-1};
943 int fx_cure_sleep_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
945 if (0) printf( "fx_cure_sleep_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
946 BASE_STATE_CURE( STATE_SLEEP );
947 target->fxqueue.RemoveAllEffects(fx_set_sleep_state_ref);
948 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_SLEEP);
949 return FX_NOT_APPLIED;
952 // 0x03 Cure:Berserk
953 // this effect clears the STATE_BERSERK (2) bit, but bg2 actually ignores the bit
954 // it also removes effect 04
955 static EffectRef fx_set_berserk_state_ref={"State:Berserk",NULL,-1};
957 int fx_cure_berserk_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
959 if (0) printf( "fx_cure_berserk_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
960 BASE_STATE_CURE( STATE_BERSERK );
961 target->fxqueue.RemoveAllEffects(fx_set_berserk_state_ref);
962 return FX_NOT_APPLIED;
965 // 0x04 State:Berserk
966 // this effect sets the STATE_BERSERK bit, but bg2 actually ignores the bit
967 int fx_set_berserk_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
969 if (0) printf( "fx_set_berserk_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
971 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
972 BASE_STATE_SET( STATE_BERSERK );
973 } else {
974 STATE_SET( STATE_BERSERK );
977 switch(fx->Parameter2) {
978 case 1: //always berserk
979 target->SetSpellState(SS_BERSERK);
980 default:
981 target->AddPortraitIcon(PI_BERSERK);
982 break;
983 case 2: //blood rage
984 target->SetSpellState(SS_BERSERK);
985 //immunity to effects:
986 //5 charm
987 //0x11 heal
988 //0x18 panic
989 //0x27 sleep
990 //0x2d stun
991 //0x6d hold
992 //0x80 confusion
993 //400 hopelessness
995 target->SetSpellState(SS_BLOODRAGE);
996 target->SetSpellState(SS_NOHPINFO);
997 target->SetColorMod(0xff, RGBModifier::ADD, 15, 128, 0, 0);
998 target->AddPortraitIcon(PI_BLOODRAGE);
999 break;
1001 return FX_PERMANENT;
1004 // 0x05 State:Charmed
1005 // 0xf1 ControlCreature (iwd2)
1006 int fx_set_charmed_state (Scriptable* Owner, Actor* target, Effect* fx)
1008 if (0) printf( "fx_set_charmed_state (%2d): General: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1010 //blood rage berserking gives immunity to charm (in iwd2)
1011 if (target->HasSpellState(SS_BLOODRAGE)) {
1012 return FX_NOT_APPLIED;
1015 //protection from evil gives immunity to charm (in iwd2)
1016 if (target->HasSpellState(SS_PROTFROMEVIL)) {
1017 return FX_NOT_APPLIED;
1020 if (fx->Parameter1 && (STAT_GET(IE_GENERAL)!=fx->Parameter1)) {
1021 return FX_NOT_APPLIED;
1023 bool enemyally = true;
1024 if (Owner->Type==ST_ACTOR) {
1025 enemyally = ((Actor *) Owner)->GetStat(IE_EA)>EA_GOODCUTOFF; //or evilcutoff?
1028 switch (fx->Parameter2) {
1029 case 0: //charmed (target neutral after charm)
1030 displaymsg->DisplayConstantStringName(STR_CHARMED, 0xf0f0f0, target);
1031 case 1000:
1032 break;
1033 case 1: //charmed (target hostile after charm)
1034 displaymsg->DisplayConstantStringName(STR_CHARMED, 0xf0f0f0, target);
1035 case 1001:
1036 if (!target->InParty) {
1037 target->SetBaseNoPCF(IE_EA, EA_ENEMY);
1039 break;
1040 case 2: //dire charmed (target neutral after charm)
1041 displaymsg->DisplayConstantStringName(STR_DIRECHARMED, 0xf0f0f0, target);
1042 case 1002:
1043 break;
1044 case 3: //dire charmed (target hostile after charm)
1045 displaymsg->DisplayConstantStringName(STR_DIRECHARMED, 0xf0f0f0, target);
1046 case 1003:
1047 if (!target->InParty) {
1048 target->SetBaseNoPCF(IE_EA, EA_ENEMY);
1050 break;
1051 case 4: //controlled by cleric
1052 displaymsg->DisplayConstantStringName(STR_CONTROLLED, 0xf0f0f0, target);
1053 case 1004:
1054 if (!target->InParty) {
1055 target->SetBaseNoPCF(IE_EA, EA_ENEMY);
1057 break;
1058 case 5: //thrall (typo comes from original engine doc)
1059 displaymsg->DisplayConstantStringName(STR_CHARMED, 0xf0f0f0, target);
1060 case 1005:
1061 STAT_SET(IE_EA, EA_ENEMY );
1062 STAT_SET(IE_THRULLCHARM, 1);
1063 return FX_PERMANENT;
1066 STATE_SET( STATE_CHARMED );
1067 STAT_SET_PCF( IE_EA, enemyally?EA_ENEMY:EA_CHARMED );
1068 //don't stick if permanent
1069 return FX_PERMANENT;
1072 // 0x06 CharismaModifier
1073 int fx_charisma_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1075 if (0) printf( "fx_charisma_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1077 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1078 BASE_MOD( IE_CHR );
1079 } else {
1080 STAT_MOD( IE_CHR );
1082 return FX_PERMANENT;
1085 // 0x07 Color:SetPalette
1086 // this effect might not work in pst, they don't have separate weapon slots
1087 int fx_set_color_gradient (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1089 if (0) printf( "fx_set_color_gradient (%2d): Gradient: %d, Location: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1090 EffectQueue::HackColorEffects(target, fx);
1091 target->SetColor( fx->Parameter2, fx->Parameter1 );
1092 return FX_APPLIED;
1095 // 08 Color:SetRGB
1096 int fx_set_color_rgb (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1098 if (0) printf( "fx_set_color_rgb (%2d): RGB: %x, Location: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1099 EffectQueue::HackColorEffects(target, fx);
1100 ieDword location = fx->Parameter2 & 0xff;
1101 target->SetColorMod(location, RGBModifier::ADD, -1, fx->Parameter1 >> 8,
1102 fx->Parameter1 >> 16, fx->Parameter1 >> 24);
1104 return FX_APPLIED;
1106 // 08 Color:SetRGBGlobal
1107 int fx_set_color_rgb_global (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1109 if (0) printf( "fx_set_color_rgb_global (%2d): RGB: %x, Location: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1111 target->SetColorMod(0xff, RGBModifier::ADD, -1, fx->Parameter1 >> 8,
1112 fx->Parameter1 >> 16, fx->Parameter1 >> 24);
1114 return FX_APPLIED;
1117 // 09 Color:PulseRGB
1118 int fx_set_color_pulse_rgb (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1120 if (0) printf( "fx_set_color_pulse_rgb (%2d): RGB: %x, Location: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1121 EffectQueue::HackColorEffects(target, fx);
1122 ieDword location = fx->Parameter2 & 0xff;
1123 int speed = (fx->Parameter2 >> 16) & 0xFF;
1124 target->SetColorMod(location, RGBModifier::ADD, speed,
1125 fx->Parameter1 >> 8, fx->Parameter1 >> 16,
1126 fx->Parameter1 >> 24);
1128 return FX_APPLIED;
1131 // 09 Color:PulseRGBGlobal (pst variant)
1132 int fx_set_color_pulse_rgb_global (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1134 if (0) printf( "fx_set_color_pulse_rgb_global (%2d): RGB: %x, Location: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1136 int speed = (fx->Parameter2 >> 16) & 0xFF;
1137 target->SetColorMod(0xff, RGBModifier::ADD, speed,
1138 fx->Parameter1 >> 8, fx->Parameter1 >> 16,
1139 fx->Parameter1 >> 24);
1141 return FX_APPLIED;
1144 // 0x0A ConstitutionModifier
1145 int fx_constitution_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1147 if (0) printf( "fx_constitution_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1149 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1150 BASE_MOD( IE_CON );
1151 } else {
1152 STAT_MOD( IE_CON );
1154 return FX_PERMANENT;
1157 // 0x0B Cure:Poison
1158 static EffectRef fx_poisoned_state_ref={"State:Poisoned",NULL,-1};
1160 int fx_cure_poisoned_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1162 if (0) printf( "fx_cure_poisoned_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1163 //all three steps are present in bg2 and iwd2
1164 BASE_STATE_CURE( STATE_POISONED );
1165 target->fxqueue.RemoveAllEffects( fx_poisoned_state_ref );
1166 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_POISONED);
1167 return FX_NOT_APPLIED;
1170 // 0x0c Damage
1171 // this is a very important effect
1172 int fx_damage (Scriptable* Owner, Actor* target, Effect* fx)
1174 if (0) printf( "fx_damage (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1175 //save for half damage type
1176 ieDword damagetype = fx->Parameter2>>16;
1177 ieDword modtype = fx->Parameter2&3;
1178 if (modtype==3) {
1179 modtype&=~3;
1181 Scriptable *caster = GetCaster(Owner, fx);
1183 target->Damage(fx->Parameter1, damagetype, caster, modtype);
1184 //this effect doesn't stick
1185 return FX_NOT_APPLIED;
1188 // 0x0d Death
1189 int fx_death (Scriptable* Owner, Actor* target, Effect* fx)
1191 if (0) printf( "fx_death (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1192 STAT_SET(IE_MINHITPOINTS,0); //the die opcode seems to override minhp
1193 ieDword damagetype = 0;
1194 switch (fx->Parameter2) {
1195 case 1:
1196 BASE_STATE_SET(STATE_D4); //not sure, should be charred
1197 damagetype = DAMAGE_FIRE;
1198 break;
1199 case 2:
1200 damagetype = DAMAGE_CRUSHING;
1201 break;
1202 case 4:
1203 damagetype = DAMAGE_CRUSHING;
1204 break;
1205 case 8:
1206 damagetype = DAMAGE_CRUSHING|DAMAGE_CHUNKING;
1207 break;
1208 case 16:
1209 BASE_STATE_SET(STATE_PETRIFIED);
1210 damagetype = DAMAGE_CRUSHING;
1211 break;
1212 case 32:
1213 BASE_STATE_SET(STATE_FROZEN);
1214 damagetype = DAMAGE_COLD;
1215 break;
1216 case 64:
1217 BASE_STATE_SET(STATE_PETRIFIED);
1218 damagetype = DAMAGE_CRUSHING|DAMAGE_CHUNKING;
1219 break;
1220 case 128:
1221 BASE_STATE_SET(STATE_FROZEN);
1222 damagetype = DAMAGE_COLD|DAMAGE_CHUNKING;
1223 break;
1224 case 256:
1225 damagetype = DAMAGE_ELECTRICITY;
1226 break;
1227 case 512:
1229 default:
1230 damagetype = DAMAGE_ACID;
1232 target->Damage(0, damagetype, Owner);
1233 //death has damage type too
1234 target->Die(Owner);
1235 //this effect doesn't stick
1236 return FX_NOT_APPLIED;
1239 // 0xE Cure:Defrost
1240 int fx_cure_frozen_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1242 if (0) printf( "fx_cure_frozen_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1243 BASE_STATE_CURE( STATE_FROZEN );
1244 return FX_NOT_APPLIED;
1247 // 0x0F DexterityModifier
1249 #define CSA_DEX 0
1250 #define CSA_STR 1
1251 #define CSA_CNT 2
1252 int SpellAbilityDieRoll(Actor *target, int which)
1254 if (which>=CSA_CNT) return 6;
1256 ieDword cls = STAT_GET(IE_CLASS);
1257 if (!spell_abilities) {
1258 AutoTable tab("clssplab");
1259 if (!tab) {
1260 spell_abilities = (int *) malloc(sizeof(int)*CSA_CNT);
1261 for (int ab=0;ab<CSA_CNT;ab++) {
1262 spell_abilities[ab*splabcount]=6;
1264 splabcount=1;
1265 return 6;
1267 splabcount = tab->GetRowCount();
1268 spell_abilities=(int *) malloc(sizeof(int)*splabcount*CSA_CNT);
1269 for (int ab=0;ab<CSA_CNT;ab++) {
1270 for (ieDword i=0;i<splabcount;i++) {
1271 spell_abilities[ab*splabcount+i]=atoi(tab->QueryField(i,ab));
1275 if (cls>=splabcount) cls=0;
1276 return spell_abilities[which*splabcount+cls];
1279 int fx_dexterity_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1281 if (0) printf( "fx_dexterity_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1283 ////how cat's grace: value is based on class
1284 if (fx->Parameter2==3) {
1285 fx->Parameter1 = core->Roll(1,SpellAbilityDieRoll(target,0),0);
1286 fx->Parameter2 = 0;
1289 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1290 BASE_MOD( IE_DEX );
1291 } else {
1292 STAT_MOD( IE_DEX );
1294 return FX_PERMANENT;
1297 static EffectRef fx_set_slow_state_ref={"State:Slowed",NULL,-1};
1298 // 0x10 State:Hasted
1299 // this function removes slowed state, or sets hasted state
1300 int fx_set_hasted_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1302 if (0) printf( "fx_set_hasted_state (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
1303 target->fxqueue.RemoveAllEffects(fx_set_slow_state_ref);
1304 target->fxqueue.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref, PI_SLOWED );
1305 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1306 BASE_STATE_CURE( STATE_SLOWED );
1307 BASE_STATE_SET( STATE_HASTED );
1308 } else {
1309 STATE_CURE( STATE_SLOWED );
1310 STATE_SET( STATE_HASTED );
1312 target->NewStat(IE_MOVEMENTRATE, 200, MOD_PERCENT);
1313 switch (fx->Parameter2) {
1314 case 0: //normal haste
1315 target->AddPortraitIcon(PI_HASTED);
1316 STAT_SET(IE_IMPROVEDHASTE,0);
1317 STAT_SET(IE_ATTACKNUMBERDOUBLE,0);
1318 STAT_ADD(IE_NUMBEROFATTACKS, 2);
1319 // -2 initiative bonus
1320 STAT_ADD(IE_PHYSICALSPEED, 2);
1321 break;
1322 case 1://improved haste
1323 target->AddPortraitIcon(PI_IMPROVEDHASTE);
1324 STAT_SET(IE_IMPROVEDHASTE,1);
1325 STAT_SET(IE_ATTACKNUMBERDOUBLE,0);
1326 target->NewStat(IE_NUMBEROFATTACKS, 200, MOD_PERCENT);
1327 // -2 initiative bonus
1328 STAT_ADD(IE_PHYSICALSPEED, 2);
1329 break;
1330 case 2://speed haste only
1331 target->AddPortraitIcon(PI_HASTED);
1332 STAT_SET(IE_IMPROVEDHASTE,0);
1333 STAT_SET(IE_ATTACKNUMBERDOUBLE,1);
1334 break;
1337 return FX_PERMANENT;
1340 // 0x11 CurrentHPModifier
1341 int fx_current_hp_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1343 if (0) printf( "fx_current_hp_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1345 if (fx->Parameter2&0x10000) {
1346 target->Resurrect();
1348 if (fx->Parameter2&0x20000) {
1349 target->fxqueue.RemoveAllNonPermanentEffects();
1351 //Cannot heal bloodrage
1352 if (target->HasSpellState(SS_BLOODRAGE)) {
1353 return FX_NOT_APPLIED;
1356 target->NewBase( IE_HITPOINTS, fx->Parameter1, fx->Parameter2&0xffff);
1357 //never stay permanent
1358 return FX_NOT_APPLIED;
1361 // 0x12 MaximumHPModifier
1362 // 0 and 3 differ in that 3 doesn't modify current hitpoints
1363 // 1,4 are the same
1364 // 2,5 are the same
1365 int fx_maximum_hp_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1367 if (0) printf( "fx_maximum_hp_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1369 bool base = fx->TimingMode==FX_DURATION_INSTANT_PERMANENT;
1371 switch (fx->Parameter2) {
1372 case 0:
1373 // random value Parameter1 is set by level_check in EffectQueue
1374 if (base) {
1375 BASE_ADD( IE_MAXHITPOINTS, fx->Parameter1 );
1376 BASE_ADD( IE_HITPOINTS, fx->Parameter1 );
1377 } else {
1378 STAT_ADD( IE_MAXHITPOINTS, fx->Parameter1 );
1379 if (fx->FirstApply) {
1380 BASE_ADD( IE_HITPOINTS, fx->Parameter1 );
1383 break;
1384 case 3:
1385 // random value Parameter1 is set by level_check in EffectQueue
1386 if (base) {
1387 BASE_ADD( IE_MAXHITPOINTS, fx->Parameter1 );
1388 } else {
1389 STAT_ADD( IE_MAXHITPOINTS, fx->Parameter1 );
1391 break;
1392 case 1:case 4:
1393 if (base) {
1394 BASE_SET( IE_MAXHITPOINTS, fx->Parameter1 );
1395 } else {
1396 STAT_SET( IE_MAXHITPOINTS, fx->Parameter1 );
1398 break;
1399 case 2:case 5:
1400 if (base) {
1401 BASE_MUL( IE_MAXHITPOINTS, fx->Parameter1 );
1402 } else {
1403 STAT_MUL( IE_MAXHITPOINTS, fx->Parameter1 );
1405 break;
1407 return FX_PERMANENT;
1410 // 0x13 IntelligenceModifier
1411 int fx_intelligence_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1413 if (0) printf( "fx_intelligence_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1415 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1416 BASE_MOD( IE_INT );
1417 } else {
1418 STAT_MOD( IE_INT );
1420 return FX_PERMANENT;
1423 // 0x14 State:Invisible
1424 // this is more complex, there is a half-invisibility state
1425 // and there is a hidden state
1426 int fx_set_invisible_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1428 switch (fx->Parameter2) {
1429 case 0:
1430 STATE_SET( STATE_INVISIBLE );
1431 STAT_ADD(IE_TOHIT, 4);
1432 break;
1433 case 1:
1434 STATE_SET( STATE_INVIS2 );
1435 HandleBonus(target, IE_ARMORCLASS, 4, fx->TimingMode);
1436 break;
1437 default:
1438 break;
1440 ieDword Trans = fx->Parameter4;
1441 if (fx->Parameter3) {
1442 if (Trans>=240) {
1443 fx->Parameter3=0;
1444 } else {
1445 Trans+=16;
1447 } else {
1448 if (Trans<=32) {
1449 fx->Parameter3=1;
1450 } else {
1451 Trans-=16;
1454 fx->Parameter4=Trans;
1455 STAT_SET( IE_TRANSLUCENT, Trans);
1456 return FX_APPLIED;
1459 // 0x15 LoreModifier
1460 int fx_lore_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1462 if (0) printf( "fx_lore_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1464 STAT_MOD( IE_LORE );
1465 return FX_APPLIED;
1468 // 0x16 LuckModifier
1469 int fx_luck_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1471 if (0) printf( "fx_luck_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1473 STAT_MOD( IE_LUCK );
1474 STAT_MOD( IE_DAMAGELUCK );
1475 return FX_APPLIED;
1478 // 0x17 MoraleModifier
1479 int fx_morale_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1481 if (0) printf( "fx_morale_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1483 STAT_MOD( IE_MORALE );
1484 return FX_APPLIED;
1487 // 0x18 State:Panic
1488 int fx_set_panic_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1490 if (0) printf( "fx_set_panic_state (%2d)\n", fx->Opcode );
1492 if (target->HasSpellState(SS_BLOODRAGE)) {
1493 return FX_NOT_APPLIED;
1496 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1497 BASE_STATE_SET( STATE_PANIC );
1498 } else {
1499 STATE_SET( STATE_PANIC );
1501 if (enhanced_effects) {
1502 target->AddPortraitIcon(PI_PANIC);
1504 return FX_PERMANENT;
1507 // 0x19 State:Poisoned
1508 int fx_set_poisoned_state (Scriptable* Owner, Actor* target, Effect* fx)
1510 if (0) printf( "fx_set_poisoned_state (%2d): Damage: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1511 //apparently this bit isn't set, but then why is it here
1512 //this requires a little research
1513 STATE_SET( STATE_POISONED );
1514 //also this effect is executed every update
1515 ieDword damage;
1516 int tmp = fx->Parameter1;
1518 HandlePercentageDamage(fx, target);
1520 switch(fx->Parameter2) {
1521 case RPD_ROUNDS:
1522 tmp *= ROUND_SECONDS;
1523 damage = 1;
1524 break;
1525 case RPD_TURNS:
1526 tmp *= ROUND_PER_TURN*ROUND_SECONDS;
1527 damage = 1;
1528 break;
1529 case RPD_SECONDS:
1530 damage = 1;
1531 break;
1532 case RPD_PERCENT: // handled in HandlePercentageDamage
1533 case RPD_POINTS:
1534 tmp = 1; // hit points per second
1535 damage = fx->Parameter1;
1536 break;
1537 default:
1538 tmp = 1;
1539 damage = 1;
1540 break;
1543 // all damage is at most per-second
1544 tmp *= AI_UPDATE_TIME;
1545 if (tmp && (core->GetGame()->GameTime%tmp)) {
1546 return FX_APPLIED;
1549 Scriptable *caster = GetCaster(Owner, fx);
1551 //percent
1552 target->Damage(damage, DAMAGE_POISON, caster);
1553 return FX_APPLIED;
1556 // 0x1a RemoveCurse
1557 static EffectRef fx_apply_effect_curse_ref={"ApplyEffectCurse",NULL,-1};
1558 static EffectRef fx_pst_jumble_curse_ref={"JumbleCurse",NULL,-1};
1560 // gemrb extension: if the resource field is filled, it will remove curse only from the specified item
1561 int fx_remove_curse (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1563 if (0) printf( "fx_remove_curse (%2d): Resource: %s Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
1565 switch(fx->Parameter2)
1567 case 1:
1568 //this is pst specific
1569 target->fxqueue.RemoveAllEffects(fx_pst_jumble_curse_ref);
1570 break;
1571 default:
1572 Inventory *inv = &target->inventory;
1573 int i = target->inventory.GetSlotCount();
1574 while(i--) {
1575 //does this slot need unequipping
1576 if (core->QuerySlotEffects(i) ) {
1577 if (fx->Resource[0] && strnicmp(inv->GetSlotItem(i)->ItemResRef, fx->Resource,8) ) {
1578 continue;
1580 if (!(inv->GetItemFlag(i)&IE_INV_ITEM_CURSED)) {
1581 continue;
1583 inv->ChangeItemFlag(i, IE_INV_ITEM_CURSED, BM_NAND);
1584 if (inv->UnEquipItem(i,true)) {
1585 CREItem *tmp = inv->RemoveItem(i);
1586 if(inv->AddSlotItem(tmp,-3)!=ASI_SUCCESS) {
1587 //if the item couldn't be placed in the inventory, then put it back to the original slot
1588 inv->SetSlotItem(tmp,i);
1589 //and drop it in the area. (If there is no area, then the item will stay in the inventory)
1590 target->DropItem(i,0);
1595 target->fxqueue.RemoveAllEffects(fx_apply_effect_curse_ref);
1598 //this is an instant effect
1599 return FX_NOT_APPLIED;
1602 // 0x1b AcidResistanceModifier
1603 int fx_acid_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1605 if (0) printf( "fx_acid_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1607 STAT_MOD( IE_RESISTACID );
1608 return FX_APPLIED;
1611 // 0x1c ColdResistanceModifier
1612 int fx_cold_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1614 if (0) printf( "fx_cold_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1616 STAT_MOD( IE_RESISTCOLD );
1617 return FX_APPLIED;
1620 // 0x1d ElectricityResistanceModifier
1621 int fx_electricity_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1623 if (0) printf( "fx_electricity_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1625 STAT_MOD( IE_RESISTELECTRICITY );
1626 return FX_APPLIED;
1629 // 0x1e FireResistanceModifier
1630 int fx_fire_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1632 if (0) printf( "fx_fire_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1634 STAT_MOD( IE_RESISTFIRE );
1635 return FX_APPLIED;
1638 // 0x1f MagicDamageResistanceModifier
1639 int fx_magic_damage_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1641 if (0) printf( "fx_magic_damage_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1643 STAT_MOD( IE_MAGICDAMAGERESISTANCE );
1644 return FX_APPLIED;
1647 // 0x20 Cure:Death
1648 int fx_cure_dead_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1650 if (0) printf( "fx_cure_dead_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1651 //someone should clear the internal flags related to death
1652 target->Resurrect();
1653 return FX_NOT_APPLIED;
1656 // 0x21 SaveVsDeathModifier
1657 int fx_save_vs_death_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1659 if (0) printf( "fx_save_vs_death_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1661 HandleBonus( target, IE_SAVEVSDEATH, fx->Parameter1, fx->TimingMode );
1662 return FX_APPLIED;
1665 // 0x22 SaveVsWandsModifier
1666 int fx_save_vs_wands_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1668 if (0) printf( "fx_save_vs_wands_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1670 HandleBonus( target, IE_SAVEVSWANDS, fx->Parameter1, fx->TimingMode );
1671 return FX_APPLIED;
1674 // 0x23 SaveVsPolyModifier
1675 int fx_save_vs_poly_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1677 if (0) printf( "fx_save_vs_poly_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1679 HandleBonus( target, IE_SAVEVSPOLY, fx->Parameter1, fx->TimingMode );
1680 return FX_APPLIED;
1683 // 0x24 SaveVsBreathModifier
1684 int fx_save_vs_breath_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1686 if (0) printf( "fx_save_vs_breath_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1688 HandleBonus( target, IE_SAVEVSBREATH, fx->Parameter1, fx->TimingMode );
1689 return FX_APPLIED;
1692 // 0x25 SaveVsSpellsModifier
1693 int fx_save_vs_spell_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1695 if (0) printf( "fx_save_vs_spell_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1697 HandleBonus( target, IE_SAVEVSSPELL, fx->Parameter1, fx->TimingMode );
1698 return FX_APPLIED;
1701 // 0x26 State:Silenced
1702 int fx_set_silenced_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1704 if (0) printf( "fx_set_silenced_state (%2d)\n", fx->Opcode );
1705 STATE_SET( STATE_SILENCED );
1706 return FX_APPLIED;
1709 static EffectRef fx_animation_stance_ref = {"AnimationStateChange",NULL,-1};
1711 // 0x27 State:Helpless
1712 // this effect sets both bits, but 'awaken' only removes the sleep bit
1713 // FIXME: this is probably a persistent effect
1714 int fx_set_unconscious_state (Scriptable* Owner, Actor* target, Effect* fx)
1716 if (0) printf( "fx_set_unconscious_state (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
1718 if (target->HasSpellState(SS_BLOODRAGE)) {
1719 return FX_NOT_APPLIED;
1722 if (fx->FirstApply) {
1723 Effect *newfx;
1725 newfx = EffectQueue::CreateEffectCopy(fx, fx_animation_stance_ref, 0, IE_ANI_SLEEP);
1726 core->ApplyEffect(newfx, target, Owner);
1728 delete newfx;
1731 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1732 BASE_STATE_SET( STATE_HELPLESS | STATE_SLEEP ); //don't awaken on damage
1733 } else {
1734 STATE_SET( STATE_HELPLESS | STATE_SLEEP ); //don't awaken on damage
1735 if (fx->Parameter2) {
1736 target->SetSpellState(SS_NOAWAKE);
1738 target->AddPortraitIcon(PI_SLEEP);
1740 return FX_PERMANENT;
1743 // 0x28 State:Slowed
1744 // this function removes hasted state, or sets slowed state
1745 static EffectRef fx_set_haste_state_ref={"State:Hasted",NULL,-1};
1747 int fx_set_slowed_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1749 if (0) printf( "fx_set_slowed_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1751 //iwd2 free action or aegis disables this effect
1752 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
1753 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
1755 if (STATE_GET(STATE_HASTED) ) {
1756 BASE_STATE_CURE( STATE_HASTED );
1757 target->fxqueue.RemoveAllEffects( fx_set_haste_state_ref );
1758 target->fxqueue.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref, PI_HASTED );
1759 } else {
1760 STATE_SET( STATE_SLOWED );
1761 target->AddPortraitIcon(PI_SLOWED);
1762 // halve apr and speed
1763 STAT_MUL(IE_NUMBEROFATTACKS, 50);
1764 STAT_MUL(IE_MOVEMENTRATE, 50);
1766 return FX_PERMANENT;
1769 // 0x29 Sparkle
1770 int fx_sparkle (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1772 if (0) printf( "fx_sparkle (%2d): Sparkle colour: %d ; Sparkle type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1773 if (!target) {
1774 return FX_NOT_APPLIED;
1777 Map *map = target->GetCurrentArea();
1778 if (!map) {
1779 return FX_APPLIED;
1781 Point p(fx->PosX, fx->PosY);
1783 //the IE programmers did something unexpected, again, a permutation!
1784 unsigned int idx;
1786 if (fx->Parameter1<SPARK_COUNT) {
1787 idx = spark_color_indices[fx->Parameter1];
1789 else {
1790 idx=fx->Parameter1;
1792 map->Sparkle( idx, fx->Parameter2, p, fx->Parameter3);
1793 return FX_NOT_APPLIED;
1796 // 0x2A WizardSpellSlotsModifier
1797 int fx_bonus_wizard_spells (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1799 if (0) printf( "fx_bonus_wizard_spells (%2d): Spell Add: %d ; Spell Level: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1801 int i=1;
1802 //if param2 is 0, then double spells up to param1
1803 if(!fx->Parameter2) {
1804 for (unsigned int j=0;j<fx->Parameter1 && j<MAX_SPELL_LEVEL;j++) {
1805 target->spellbook.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD, j, true);
1807 return FX_APPLIED;
1809 //HoW specific
1810 //if param2 is 0x200, then double spells at param1
1811 if (fx->Parameter2==0x200) {
1812 unsigned int j = fx->Parameter1-1;
1813 if (j<MAX_SPELL_LEVEL) {
1814 target->spellbook.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD, j, true);
1818 for(unsigned int j=0;j<MAX_SPELL_LEVEL;j++) {
1819 if (fx->Parameter2&i) {
1820 target->spellbook.SetMemorizableSpellsCount(fx->Parameter1, IE_SPELL_TYPE_WIZARD, j, true);
1822 i<<=1;
1824 return FX_APPLIED;
1827 // 0x2B Cure:Petrification
1828 int fx_cure_petrified_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1830 if (0) printf( "fx_cure_petrified_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1831 BASE_STATE_CURE( STATE_PETRIFIED );
1832 return FX_NOT_APPLIED;
1835 // 0x2C StrengthModifier
1836 int fx_strength_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1838 if (0) printf( "fx_strength_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1840 ////how strength: value is based on class
1841 if (fx->Parameter2==3) {
1842 fx->Parameter1 = core->Roll(1,SpellAbilityDieRoll(target,1),0);
1843 fx->Parameter2 = 0;
1846 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1847 BASE_MOD( IE_STR );
1848 } else {
1849 STAT_MOD( IE_STR );
1851 return FX_PERMANENT;
1854 // 0x2D State:Stun
1855 int power_word_stun_iwd2(Actor *target, Effect *fx)
1857 int hp = BASE_GET(IE_HITPOINTS);
1858 if (hp>150) return FX_NOT_APPLIED;
1859 int stuntime;
1860 if (hp>100) stuntime = core->Roll(1,4,0);
1861 else if (hp>50) stuntime = core->Roll(2,4,0);
1862 else stuntime = core->Roll(4,4,0);
1863 fx->Parameter2 = 0;
1864 fx->TimingMode = FX_DURATION_ABSOLUTE;
1865 fx->Duration = stuntime*6*ROUND_SIZE + core->GetGame()->GameTime;
1866 STATE_SET( STATE_STUNNED );
1867 target->AddPortraitIcon(PI_STUN);
1868 return FX_APPLIED;
1871 int fx_set_stun_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1873 if (0) printf( "fx_set_stun_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1875 if ( STATE_GET(STATE_DEAD) ) {
1876 return FX_NOT_APPLIED;
1879 if (target->HasSpellState(SS_BLOODRAGE)) {
1880 return FX_NOT_APPLIED;
1883 if (fx->Parameter2==2) {
1884 return power_word_stun_iwd2(target, fx);
1886 STATE_SET( STATE_STUNNED );
1887 target->AddPortraitIcon(PI_STUN);
1888 if (fx->Parameter2==1) {
1889 target->SetSpellState(SS_AWAKE);
1891 return FX_APPLIED;
1894 // 0x2E Cure:Stun
1895 static EffectRef fx_set_stun_state_ref={"State:Stun",NULL,-1};
1896 static EffectRef fx_hold_creature_no_icon_ref={"State:Hold3",NULL,-1};
1898 int fx_cure_stun_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1900 if (0) printf( "fx_cure_stun_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1901 BASE_STATE_CURE( STATE_STUNNED );
1902 target->fxqueue.RemoveAllEffects(fx_set_stun_state_ref);
1903 target->fxqueue.RemoveAllEffects(fx_hold_creature_no_icon_ref);
1904 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_HELD);
1905 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_HOPELESS);
1906 return FX_NOT_APPLIED;
1909 // 0x2F Cure:Invisible
1910 // 0x74 Cure:Invisible2
1911 static EffectRef fx_set_invisible_state_ref={"State:Invisible",NULL,-1};
1913 int fx_cure_invisible_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1915 if (0) printf( "fx_cure_invisible_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1916 if (!STATE_GET(STATE_NONDET)) {
1917 BASE_STATE_CURE( STATE_INVISIBLE | STATE_INVIS2 );
1918 target->fxqueue.RemoveAllEffects(fx_set_invisible_state_ref);
1920 return FX_NOT_APPLIED;
1923 // 0x30 Cure:Silence
1924 static EffectRef fx_set_silenced_state_ref={"State:Silenced",NULL,-1};
1926 int fx_cure_silenced_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1928 if (0) printf( "fx_cure_silenced_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1929 BASE_STATE_CURE( STATE_SILENCED );
1930 target->fxqueue.RemoveAllEffects(fx_set_silenced_state_ref);
1931 return FX_NOT_APPLIED;
1934 // 0x31 WisdomModifier
1935 int fx_wisdom_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1937 if (0) printf( "fx_wisdom_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1939 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
1940 BASE_MOD( IE_WIS );
1941 } else {
1942 STAT_MOD( IE_WIS );
1944 return FX_PERMANENT;
1947 // 0x32 Color:BriefRGB
1948 int fx_brief_rgb (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1950 if (0) printf( "fx_brief_rgb (%2d): RGB: %d, Location and speed: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1952 int speed = (fx->Parameter2 >> 16) & 0xff;
1953 target->SetColorMod(0xff, RGBModifier::ADD, speed,
1954 fx->Parameter1 >> 8, fx->Parameter1 >> 16,
1955 fx->Parameter1 >> 24, 0);
1957 return FX_NOT_APPLIED;
1960 // 0x33 Color:DarkenRGB
1961 int fx_darken_rgb (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1963 if (0) printf( "fx_darken_rgb (%2d): RGB: %d, Location and speed: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1964 EffectQueue::HackColorEffects(target, fx);
1965 ieDword location = fx->Parameter2 & 0xff;
1966 target->SetColorMod(location, RGBModifier::TINT, -1, fx->Parameter1 >> 8,
1967 fx->Parameter1 >> 16, fx->Parameter1 >> 24);
1968 return FX_APPLIED;
1971 // 0x34 Color:GlowRGB
1972 int fx_glow_rgb (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1974 if (0) printf( "fx_glow_rgb (%2d): RGB: %d, Location and speed: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1975 EffectQueue::HackColorEffects(target, fx);
1976 ieDword location = fx->Parameter2 & 0xff;
1977 target->SetColorMod(location, RGBModifier::BRIGHTEN, -1,
1978 fx->Parameter1 >> 8, fx->Parameter1 >> 16,
1979 fx->Parameter1 >> 24);
1981 return FX_APPLIED;
1984 // 0x35 AnimationIDModifier
1985 static EffectRef fx_animation_id_modifier_ref={"AnimationIDModifier",NULL,-1};
1987 int fx_animation_id_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
1989 if (0) printf( "fx_animation_id_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
1991 switch (fx->Parameter2) {
1992 case 0: //non permanent animation change
1993 default:
1994 STAT_SET( IE_ANIMATION_ID, fx->Parameter1 );
1995 return FX_APPLIED;
1996 case 1: //remove any non permanent change
1997 target->fxqueue.RemoveAllEffects(fx_animation_id_modifier_ref);
1998 //return FX_NOT_APPLIED;
1999 //intentionally passing through (perma change removes previous changes)
2000 case 2: //permanent animation id change
2001 target->SetBaseNoPCF(IE_ANIMATION_ID, fx->Parameter1);
2002 return FX_NOT_APPLIED;
2006 // 0x36 ToHitModifier
2007 int fx_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2009 if (0) printf( "fx_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2011 HandleBonus( target, IE_TOHIT, fx->Parameter1, fx->TimingMode );
2012 return FX_APPLIED;
2015 // 0x37 KillCreatureType
2016 static EffectRef fx_death_ref={"Death",NULL,-1};
2018 int fx_kill_creature_type (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2020 if (0) printf( "fx_kill_creature_type (%2d): Value: %d, IDS: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2021 if (EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
2022 //convert it to a death opcode or apply the new effect?
2023 fx->Opcode = EffectQueue::ResolveEffect(fx_death_ref);
2024 fx->TimingMode = FX_DURATION_INSTANT_PERMANENT;
2025 fx->Parameter1 = 0;
2026 fx->Parameter2 = 4;
2027 return FX_APPLIED;
2029 //doesn't stick
2030 return FX_NOT_APPLIED;
2033 // 0x38 Alignment:Invert
2034 //switch good to evil and evil to good
2035 //also switch chaotic to lawful and vice versa
2036 //gemrb extension: param2 actually controls which parts should be reversed
2037 // 0 - switch both (as original)
2038 // 1 - switch good and evil
2039 // 2 - switch lawful and chaotic
2041 static int al_switch_both[16]={0,0x33,0x32,0x31,0,0x23,0x22,0x21,0,0x13,0x12,0x11};
2042 static int al_switch_law[16]={0,0x31,0x32,0x33,0,0x21,0x22,0x23,0,0x11,0x12,0x13};
2043 static int al_switch_good[16]={0,0x13,0x12,0x11,0,0x23,0x22,0x21,0,0x33,0x32,0x31};
2044 int fx_alignment_invert (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2046 if (0) printf( "fx_alignment_invert (%2d)\n", fx->Opcode );
2047 register ieDword newalign = target->GetStat( IE_ALIGNMENT );
2048 //compress the values. GNE is the first 2 bits originally
2049 //LNC is the 4/5. bits.
2050 newalign = (newalign & AL_GE_MASK) | ((newalign & AL_LC_MASK)>>2);
2051 switch (fx->Parameter2) {
2052 default:
2053 newalign = al_switch_both[newalign];
2054 break;
2055 case 1: //switch good/evil
2056 newalign = al_switch_good[newalign];
2057 break;
2058 case 2:
2059 newalign = al_switch_law[newalign];
2060 break;
2062 STAT_SET( IE_ALIGNMENT, newalign );
2063 return FX_APPLIED;
2066 // 0x39 Alignment:Change
2067 int fx_alignment_change (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2069 if (0) printf( "fx_alignment_change (%2d): Value: %d\n", fx->Opcode, fx->Parameter2 );
2070 STAT_SET( IE_ALIGNMENT, fx->Parameter2 );
2071 return FX_APPLIED;
2074 // 0x3a DispelEffects
2075 int fx_dispel_effects (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2077 if (0) printf( "fx_dispel_effects (%2d): Value: %d, IDS: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2078 ieDword level;
2080 switch (fx->Parameter2) {
2081 case 0:
2082 default:
2083 level = 0xffffffff;
2084 break;
2085 case 1:
2086 //same level: 50% success, each diff modifies it by 5%
2087 level = core->Roll(1,20,fx->Power-10);
2088 if (level>=0x80000000) level = 0;
2089 break;
2090 case 2:
2091 //same level: 50% success, each diff modifies it by 5%
2092 level = core->Roll(1,20,fx->Parameter1-10);
2093 if (level>=0x80000000) level = 0;
2094 break;
2096 //if signed would it be negative?
2097 target->fxqueue.RemoveLevelEffects(level, RL_DISPELLABLE, 0);
2098 return FX_NOT_APPLIED;
2101 // 0x3B StealthModifier
2102 int fx_stealth_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2104 if (0) printf( "fx_stealth_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2106 STAT_MOD( IE_STEALTH );
2107 return FX_APPLIED;
2110 // 0x3C MiscastMagicModifier
2111 int fx_miscast_magic_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2113 if (0) printf( "fx_miscast_magic_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2115 switch (fx->Parameter2) {
2116 case 3:
2117 STAT_SET( IE_DEADMAGIC, 1);
2118 case 0:
2119 STAT_SET( IE_SPELLFAILUREMAGE, fx->Parameter1);
2120 break;
2121 case 4:
2122 STAT_SET( IE_DEADMAGIC, 1);
2123 case 1:
2124 STAT_SET( IE_SPELLFAILUREPRIEST, fx->Parameter1);
2125 break;
2126 case 5:
2127 STAT_SET( IE_DEADMAGIC, 1);
2128 case 2:
2129 STAT_SET( IE_SPELLFAILUREINNATE, fx->Parameter1);
2130 break;
2131 default:
2132 return FX_NOT_APPLIED;
2134 return FX_APPLIED;
2137 // 0x3D AlchemyModifier
2138 // this crashes in bg2 due to assertion failure (disabled intentionally)
2139 // and in iwd it doesn't really follow the stat_mod convention (quite lame)
2140 int fx_alchemy_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2142 if (0) printf( "fx_alchemy_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2144 switch(fx->Parameter2) {
2145 case 0:
2146 STAT_ADD( IE_ALCHEMY, fx->Parameter1 );
2147 break;
2148 case 1:
2149 STAT_SET( IE_ALCHEMY, fx->Parameter1 );
2150 break;
2151 case 2:
2152 STAT_SET( IE_ALCHEMY, 100 );
2153 break;
2155 return FX_APPLIED;
2158 // 0x3E PriestSpellSlotsModifier
2159 int fx_bonus_priest_spells (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2161 if (0) printf( "fx_bonus_priest_spells (%2d): Spell Add: %d ; Spell Level: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2163 int i=1;
2164 //if param2 is 0, then double spells up to param1
2165 if(!fx->Parameter2) {
2166 for (unsigned int j=0;j<fx->Parameter1 && j<MAX_SPELL_LEVEL;j++) {
2167 target->spellbook.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_PRIEST, j, true);
2169 return FX_APPLIED;
2172 //HoW specific
2173 //if param2 is 0x200, then double spells at param1
2174 if (fx->Parameter2==0x200) {
2175 unsigned int j = fx->Parameter1-1;
2176 target->spellbook.SetMemorizableSpellsCount(fx->Parameter1, IE_SPELL_TYPE_PRIEST, j, true);
2177 return FX_APPLIED;
2180 for(unsigned int j=0;j<MAX_SPELL_LEVEL;j++) {
2181 if (fx->Parameter2&i) {
2182 target->spellbook.SetMemorizableSpellsCount(fx->Parameter1, IE_SPELL_TYPE_PRIEST, j, true);
2184 i<<=1;
2186 return FX_APPLIED;
2189 // 0x3F State:Infravision
2190 int fx_set_infravision_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2192 if (0) printf( "fx_set_infravision_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2193 STATE_SET( STATE_INFRA );
2194 return FX_APPLIED;
2197 // 0x40 Cure:Infravision
2198 static EffectRef fx_set_infravision_state_ref={"State:Infravision",NULL,-1};
2200 int fx_cure_infravision_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2202 if (0) printf( "fx_cure_infravision_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2203 BASE_STATE_CURE( STATE_INFRA );
2204 target->fxqueue.RemoveAllEffects(fx_set_infravision_state_ref);
2205 return FX_NOT_APPLIED;
2208 // 0x41 State:Blur
2209 int fx_set_blur_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2211 if (0) printf( "fx_set_blur_state (%2d)\n", fx->Opcode );
2212 if (STATE_GET( STATE_DEAD) ) {
2213 return FX_NOT_APPLIED;
2215 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
2216 BASE_STATE_SET( STATE_BLUR );
2217 } else {
2218 STATE_SET( STATE_BLUR );
2220 //iwd2 specific
2221 if (enhanced_effects) {
2222 target->AddPortraitIcon(PI_BLUR);
2224 return FX_PERMANENT;
2227 // 0x42 TransparencyModifier
2228 int fx_transparency_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2230 if (0) printf( "fx_transparency_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2232 //maybe this needs some timing
2233 switch (fx->Parameter2) {
2234 case 1: //fade in
2235 if (fx->Parameter1<255) {
2236 if (core->GetGame()->GameTime%2) {
2237 fx->Parameter1++;
2240 break;
2241 case 2://fade out
2242 if (fx->Parameter1) {
2243 if (core->GetGame()->GameTime%2) {
2244 fx->Parameter1--;
2247 break;
2249 STAT_MOD( IE_TRANSLUCENT );
2250 return FX_APPLIED;
2253 // 0x43 SummonCreature
2255 static int eamods[]={EAM_ALLY,EAM_ALLY,EAM_DEFAULT,EAM_ALLY,EAM_DEFAULT,EAM_ENEMY,EAM_ALLY};
2257 int fx_summon_creature (Scriptable* Owner, Actor* target, Effect* fx)
2259 if (0) printf( "fx_summon_creature (%2d): ResRef:%s Anim:%s Type: %d\n", fx->Opcode, fx->Resource, fx->Resource2, fx->Parameter2 );
2260 if (!target) {
2261 return FX_NOT_APPLIED;
2264 if (!target->GetCurrentArea()) {
2265 return FX_APPLIED;
2268 //summon creature (resource), play vvc (resource2)
2269 //creature's lastsummoner is Owner
2270 //creature's target is target
2271 //position of appearance is target's pos
2272 int eamod = -1;
2273 if (fx->Parameter2<6){
2274 eamod = eamods[fx->Parameter2];
2277 //the monster should appear near the effect position
2278 Point p(fx->PosX, fx->PosY);
2280 Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
2281 core->SummonCreature(fx->Resource, fx->Resource2, Owner, target, p, eamod, 0, newfx);
2282 delete newfx;
2283 return FX_NOT_APPLIED;
2286 // 0x44 UnsummonCreature
2287 int fx_unsummon_creature (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2289 if (0) printf( "fx_unsummon_creature (%2d)\n", fx->Opcode );
2291 //to be compatible with the original engine, unsummon doesn't work with PC's
2292 //but it works on anything else
2293 if (!target->InParty) {
2294 //play the vanish animation
2295 ScriptedAnimation* sca = gamedata->GetScriptedAnimation(fx->Resource, false);
2296 if (sca) {
2297 sca->XPos+=target->Pos.x;
2298 sca->YPos+=target->Pos.y;
2299 target->GetCurrentArea()->AddVVCell(sca);
2301 //remove the creature
2302 target->DestroySelf();
2304 return FX_NOT_APPLIED;
2307 // 0x45 State:Nondetection
2308 int fx_set_nondetection_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2310 if (0) printf( "fx_set_nondetection_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2311 STATE_SET( STATE_NONDET );
2312 return FX_APPLIED;
2315 // 0x46 Cure:Nondetection
2316 static EffectRef fx_set_nondetection_state_ref={"State:Nondetection",NULL,-1};
2318 int fx_cure_nondetection_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2320 if (0) printf( "fx_cure_nondetection_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2321 BASE_STATE_CURE( STATE_NONDET );
2322 target->fxqueue.RemoveAllEffects(fx_set_nondetection_state_ref);
2323 return FX_NOT_APPLIED;
2326 // 0x47 SexModifier
2327 int fx_sex_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2329 if (0) printf( "fx_sex_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2330 ieDword value;
2331 if (fx->Parameter2) {
2332 value = fx->Parameter1;
2333 } else {
2334 if (STAT_GET(IE_SEX_CHANGED)) {
2335 return FX_NOT_APPLIED;
2337 STAT_SET( IE_SEX_CHANGED, 1);
2338 value = STAT_GET(IE_SEX);
2339 if (value==SEX_MALE) {
2340 value = SEX_FEMALE;
2341 } else {
2342 value = SEX_MALE;
2345 STAT_SET( IE_SEX, value );
2346 return FX_APPLIED;
2349 // 0x48 AIIdentifierModifier
2350 int fx_ids_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2352 if (0) printf( "fx_ids_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2353 switch (fx->Parameter2) {
2354 case 0:
2355 STAT_SET(IE_EA, fx->Parameter1);
2356 break;
2357 case 1:
2358 STAT_SET(IE_GENERAL, fx->Parameter1);
2359 break;
2360 case 2:
2361 STAT_SET(IE_RACE, fx->Parameter1);
2362 break;
2363 case 3:
2364 STAT_SET(IE_CLASS, fx->Parameter1);
2365 break;
2366 case 4:
2367 STAT_SET(IE_SPECIFIC, fx->Parameter1);
2368 break;
2369 case 5:
2370 STAT_SET(IE_SEX, fx->Parameter1);
2371 break;
2372 case 6:
2373 STAT_SET(IE_ALIGNMENT, fx->Parameter1);
2374 break;
2375 default:
2376 return FX_NOT_APPLIED;
2378 //not sure, need a check if this action could be permanent
2379 return FX_APPLIED;
2382 // 0x49 DamageBonusModifier
2383 int fx_damage_bonus_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2385 if (0) printf( "fx_damage_bonus_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2387 STAT_MOD( IE_DAMAGEBONUS );
2388 return FX_APPLIED;
2391 // 0x4a State:Blind
2392 int fx_set_blind_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2394 if (0) printf( "fx_set_blind_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2396 //don't do this effect twice (bug exists in BG2, but fixed in IWD2)
2397 if (!STATE_GET(STATE_BLIND)) {
2398 STATE_SET( STATE_BLIND );
2399 //the feat normally exists only in IWD2, but won't hurt
2400 if (!target->GetFeat(FEAT_BLIND_FIGHT)) {
2401 STAT_SUB (IE_TOHIT, 10); // all other tohit stats are treated as bonuses
2404 return FX_APPLIED;
2407 // 0x4b Cure:Blind
2408 static EffectRef fx_set_blind_state_ref={"State:Blind",NULL,-1};
2410 int fx_cure_blind_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2412 if (0) printf( "fx_cure_blind_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2413 BASE_STATE_CURE( STATE_BLIND );
2414 target->fxqueue.RemoveAllEffects(fx_set_blind_state_ref);
2415 return FX_NOT_APPLIED;
2418 // 0x4c State:Feeblemind
2419 int fx_set_feebleminded_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2421 if (0) printf( "fx_set_feebleminded_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2422 STATE_SET( STATE_FEEBLE );
2423 STAT_SET( IE_INT, 3);
2424 if (enhanced_effects) {
2425 target->AddPortraitIcon(PI_FEEBLEMIND);
2427 return FX_APPLIED;
2430 // 0x4d Cure:Feeblemind
2431 static EffectRef fx_set_feebleminded_state_ref={"State:Feeblemind",NULL,-1};
2433 int fx_cure_feebleminded_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2435 if (0) printf( "fx_cure_feebleminded_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2436 BASE_STATE_CURE( STATE_FEEBLE );
2437 target->fxqueue.RemoveAllEffects(fx_set_feebleminded_state_ref);
2438 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_FEEBLEMIND);
2439 return FX_NOT_APPLIED;
2442 // 0x4e State:Diseased
2443 int fx_set_diseased_state (Scriptable* Owner, Actor* target, Effect* fx)
2445 if (0) printf( "fx_set_diseased_state (%2d): Damage: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2446 //STATE_SET( STATE_DISEASED ); //no this we don't want
2448 //setting damage to 0 because not all types do damage
2449 ieDword damage = 0;
2451 HandlePercentageDamage(fx, target);
2453 switch(fx->Parameter2) {
2454 case RPD_SECONDS:
2455 damage = 1;
2456 if (fx->Parameter1 && (core->GetGame()->GameTime%(fx->Parameter1*AI_UPDATE_TIME))) {
2457 return FX_APPLIED;
2459 break;
2460 case RPD_PERCENT: // handled in HandlePercentageDamage
2461 case RPD_POINTS:
2462 damage = fx->Parameter1;
2463 // per second
2464 if (core->GetGame()->GameTime%AI_UPDATE_TIME) {
2465 return FX_APPLIED;
2467 break;
2468 case RPD_STR: //strength
2469 STAT_ADD(IE_STR, fx->Parameter1);
2470 break;
2471 case RPD_DEX: //dex
2472 STAT_ADD(IE_DEX, fx->Parameter1);
2473 break;
2474 case RPD_CON: //con
2475 STAT_ADD(IE_CON, fx->Parameter1);
2476 break;
2477 case RPD_INT: //int
2478 STAT_ADD(IE_INT, fx->Parameter1);
2479 break;
2480 case RPD_WIS: //wis
2481 STAT_ADD(IE_WIS, fx->Parameter1);
2482 break;
2483 case RPD_CHA: //cha
2484 STAT_ADD(IE_CHR, fx->Parameter1);
2485 break;
2486 case RPD_SLOW: //slow
2487 break;
2488 default:
2489 damage = 1;
2490 break;
2492 //percent
2493 Scriptable *caster = GetCaster(Owner, fx);
2495 if (damage) {
2496 target->Damage(damage, DAMAGE_POISON, caster);
2498 return FX_APPLIED;
2502 // 0x4f Cure:Disease
2503 static EffectRef fx_diseased_state_ref={"State:Diseased",NULL,-1};
2505 int fx_cure_diseased_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2507 if (0) printf( "fx_cure_diseased_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2508 //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
2509 target->fxqueue.RemoveAllEffects( fx_diseased_state_ref ); //this is what actually happens in bg2
2510 return FX_NOT_APPLIED;
2513 // 0x50 State:Deafness
2514 // gemrb extension: modifiable amount
2515 // none of the engines care about stacking
2516 int fx_set_deaf_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2518 if (0) printf( "fx_set_deaf_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2520 //gemrb fix
2521 if (target->SetSpellState(SS_DEAF)) return FX_APPLIED;
2523 if (!fx->Parameter1) {
2524 fx->Parameter1 = 50;
2526 STAT_ADD(IE_SPELLFAILUREMAGE, fx->Parameter1);
2527 if (!fx->Parameter2) {
2528 fx->Parameter1 = 50;
2530 STAT_ADD(IE_SPELLFAILUREPRIEST, fx->Parameter2);
2531 EXTSTATE_SET(EXTSTATE_DEAF); //iwd1/how needs this
2532 if (enhanced_effects) {
2533 target->AddPortraitIcon(PI_DEAFNESS);
2535 return FX_APPLIED;
2538 int fx_set_deaf_state_iwd2 (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2540 if (0) printf( "fx_set_deaf_state_iwd2 (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2542 //gemrb fix
2543 if (target->SetSpellState(SS_DEAF)) return FX_APPLIED;
2545 if (!fx->Parameter1) {
2546 //this is a bad hack
2547 fx->Parameter1 = 20;
2549 STAT_ADD(IE_SPELLFAILUREMAGE, fx->Parameter1);
2550 if (!fx->Parameter2) {
2551 fx->Parameter1 = 20;
2553 STAT_ADD(IE_SPELLFAILUREPRIEST, fx->Parameter2);
2554 EXTSTATE_SET(EXTSTATE_DEAF); //iwd1/how needs this
2555 target->AddPortraitIcon(PI_DEAFNESS); //iwd2 specific
2556 return FX_APPLIED;
2559 // 0x51 Cure:Deafness
2560 static EffectRef fx_deaf_state_ref={"State:Deafness",NULL,-1};
2561 static EffectRef fx_deaf_state_iwd2_ref={"State:DeafnessIWD2",NULL,-1};
2563 //removes the deafness effect
2564 int fx_cure_deaf_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2566 if (0) printf( "fx_cure_deaf_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2568 target->fxqueue.RemoveAllEffects(fx_deaf_state_ref);
2569 target->fxqueue.RemoveAllEffects(fx_deaf_state_iwd2_ref);
2570 return FX_NOT_APPLIED;
2573 // 0x52 SetAIScript
2574 int fx_set_ai_script (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2576 if (0) printf( "fx_set_ai_state (%2d): Resource: %s, Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
2577 target->SetScript (fx->Resource, fx->Parameter2);
2578 return FX_NOT_APPLIED;
2581 // 0x53 Protection:Projectile
2582 int fx_protection_from_projectile (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2584 if (0) printf( "fx_protection_from_projectile (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
2585 STAT_BIT_OR( IE_IMMUNITY, IMM_PROJECTILE);
2586 return FX_APPLIED;
2589 // 0x54 MagicalFireResistanceModifier
2590 int fx_magical_fire_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2592 if (0) printf( "fx_magical_fire_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2594 STAT_MOD( IE_RESISTMAGICFIRE );
2595 return FX_APPLIED;
2598 // 0x55 MagicalColdResistanceModifier
2599 int fx_magical_cold_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2601 if (0) printf( "fx_magical_cold_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2603 STAT_MOD( IE_RESISTMAGICCOLD );
2604 return FX_APPLIED;
2607 // 0x56 SlashingResistanceModifier
2608 int fx_slashing_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2610 if (0) printf( "fx_slashing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2612 STAT_MOD( IE_RESISTSLASHING );
2613 return FX_APPLIED;
2616 // 0x57 CrushingResistanceModifier
2617 int fx_crushing_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2619 if (0) printf( "fx_crushing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2621 STAT_MOD( IE_RESISTCRUSHING );
2622 return FX_APPLIED;
2625 // 0x58 PiercingResistanceModifier
2626 int fx_piercing_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2628 if (0) printf( "fx_piercing_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2630 STAT_MOD( IE_RESISTPIERCING );
2631 return FX_APPLIED;
2634 // 0x59 MissilesResistanceModifier
2635 int fx_missiles_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2637 if (0) printf( "fx_missiles_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2639 STAT_MOD( IE_RESISTMISSILE );
2640 return FX_APPLIED;
2643 // 0x5A OpenLocksModifier
2644 int fx_open_locks_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2646 if (0) printf( "fx_open_locks_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2648 STAT_MOD( IE_LOCKPICKING );
2649 return FX_APPLIED;
2652 // 0x5B FindTrapsModifier
2653 int fx_find_traps_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2655 if (0) printf( "fx_find_traps_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2657 STAT_MOD( IE_TRAPS );
2658 return FX_APPLIED;
2661 // 0x5C PickPocketsModifier
2662 int fx_pick_pockets_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2664 if (0) printf( "fx_pick_pockets_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2666 STAT_MOD( IE_PICKPOCKET );
2667 return FX_APPLIED;
2670 // 0x5D FatigueModifier
2671 int fx_fatigue_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2673 if (0) printf( "fx_fatigue_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2675 STAT_MOD( IE_FATIGUE );
2676 // TODO: fatigue has a negative effect on luck -> add fatigmod.2da support
2677 return FX_APPLIED;
2680 // 0x5E IntoxicationModifier
2681 int fx_intoxication_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2683 if (0) printf( "fx_intoxication_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2685 STAT_MOD( IE_INTOXICATION );
2686 return FX_APPLIED;
2689 // 0x5F TrackingModifier
2690 int fx_tracking_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2692 if (0) printf( "fx_tracking_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2694 STAT_MOD( IE_TRACKING );
2695 return FX_APPLIED;
2698 // 0x60 LevelModifier
2699 int fx_level_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2701 if (0) printf( "fx_level_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2703 STAT_MOD( IE_LEVEL );
2704 return FX_APPLIED;
2707 // 0x61 StrengthBonusModifier
2708 int fx_strength_bonus_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2710 if (0) printf( "fx_strength_bonus_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2712 STAT_MOD( IE_STREXTRA );
2713 return FX_APPLIED;
2716 // 0x62 State:Regenerating
2717 int fx_set_regenerating_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2719 if (0) printf( "fx_set_regenerating_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2720 int damage;
2721 int tmp = fx->Parameter1;
2722 ieDword gameTime = core->GetGame()->GameTime;
2723 ieDword nextHeal;
2725 if (!fx->Parameter3) {
2726 //hack to ensure our first call gets through
2727 nextHeal = gameTime-1;
2728 } else {
2729 nextHeal = fx->Parameter3;
2732 //we can have multiple calls at the same gameTime, so we
2733 //just go to gameTime+1 to ensure one call
2734 if (nextHeal>=gameTime) return FX_APPLIED;
2736 HandlePercentageDamage(fx, target);
2738 switch(fx->Parameter2) {
2739 case RPD_TURNS: //restore param3 hp every param1 turns
2740 //assuming 1 turn = 10 rounds
2741 tmp *= ROUND_PER_TURN;
2742 //fall
2743 case RPD_ROUNDS: //restore param3 hp every param1 rounds
2744 tmp *= ROUND_SECONDS;
2745 //fall
2746 case RPD_SECONDS: //restore param3 hp every param1 seconds
2747 fx->Parameter3 = nextHeal + tmp*AI_UPDATE_TIME;
2748 damage = 1;
2749 break;
2750 case RPD_PERCENT: // handled in HandlePercentageDamage
2751 case RPD_POINTS: //restore param1 hp every second? that's crazy!
2752 damage = fx->Parameter1;
2753 fx->Parameter3 = nextHeal + AI_UPDATE_TIME;
2754 break;
2755 default:
2756 fx->Parameter3 = nextHeal + AI_UPDATE_TIME;
2757 damage = 1;
2758 break;
2761 //This should take care of the change of the modified stat
2762 //So there is no need to do anything else here other than increasing
2763 //the base current hp
2764 target->NewBase(IE_HITPOINTS, damage, MOD_ADDITIVE);
2765 return FX_APPLIED;
2767 // 0x63 SpellDurationModifier
2768 int fx_spell_duration_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2770 if (0) printf( "fx_spell_duration_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2772 switch (fx->Parameter2) {
2773 case 0:
2774 STAT_SET( IE_SPELLDURATIONMODMAGE, fx->Parameter1);
2775 break;
2776 case 1:
2777 STAT_SET( IE_SPELLDURATIONMODPRIEST, fx->Parameter1);
2778 break;
2779 default:
2780 return FX_NOT_APPLIED;
2782 return FX_APPLIED;
2784 // 0x64 Protection:Creature
2785 int fx_generic_effect (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
2787 if (0) printf( "fx_generic_effect (%2d): Param1: %d, Param2: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2788 return FX_APPLIED;
2791 // 0x65 Protection:Opcode
2792 int fx_protection_opcode (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2794 if (0) printf( "fx_protection_opcode (%2d): Opcode: %d\n", fx->Opcode, fx->Parameter2 );
2795 STAT_BIT_OR(IE_IMMUNITY, IMM_OPCODE);
2796 return FX_APPLIED;
2799 // 0x66 Protection:SpellLevel
2800 int fx_protection_spelllevel (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2802 if (0) printf( "fx_protection_spelllevel (%2d) Level: %d\n", fx->Opcode, fx->Parameter1);
2804 int value = fx->Parameter1;
2805 if (value<9) {
2806 STAT_BIT_OR(IE_MINORGLOBE, 1<<value);
2807 STAT_BIT_OR(IE_IMMUNITY, IMM_LEVEL);
2808 return FX_APPLIED;
2810 return FX_NOT_APPLIED;
2813 // 0x67 ChangeName
2814 int fx_change_name (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2816 if (0) printf( "fx_change_name_modifier (%2d): StrRef: %d\n", fx->Opcode, fx->Parameter1 );
2817 target->SetName(fx->Parameter1, 0);
2818 return FX_NOT_APPLIED;
2821 // 0x68 ExperienceModifier
2822 int fx_experience_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2824 if (0) printf( "fx_experience_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2825 //i believe this has mode too
2826 target->AddExperience (fx->Parameter1);
2827 return FX_NOT_APPLIED;
2830 // 0x69 GoldModifier
2831 //in BG2 this effect subtracts gold when type is MOD_ADDITIVE
2832 //no one uses it, though. To keep the function, the default branch will do the subtraction
2833 int fx_gold_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2835 if (0) printf( "fx_gold_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2836 if (!target->InParty) {
2837 STAT_MOD( IE_GOLD );
2838 return FX_NOT_APPLIED;
2840 ieDword gold;
2841 Game *game = core->GetGame();
2842 //for party members, the gold is stored in the game object
2843 switch( fx->Parameter2) {
2844 case MOD_ADDITIVE:
2845 gold = fx->Parameter1;
2846 break;
2847 case MOD_ABSOLUTE:
2848 gold = fx->Parameter1-game->PartyGold;
2849 break;
2850 case MOD_PERCENT:
2851 gold = game->PartyGold*fx->Parameter1/100-game->PartyGold;
2852 break;
2853 default:
2854 gold = (ieDword) -fx->Parameter1;
2855 break;
2857 game->AddGold (gold);
2858 return FX_NOT_APPLIED;
2861 // 0x6a MoraleBreakModifier
2862 int fx_morale_break_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2864 if (0) printf( "fx_morale_break_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2865 STAT_MOD(IE_MORALEBREAK);
2866 return FX_PERMANENT; //permanent morale break doesn't stick
2869 // 0x6b PortraitChange
2870 int fx_portrait_change (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2872 if (0) printf( "fx_portrait_change (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2873 target->SetPortrait( fx->Resource, fx->Parameter2);
2874 return FX_NOT_APPLIED;
2877 // 0x6c ReputationModifier
2878 int fx_reputation_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2880 if (0) printf( "fx_reputation_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2881 STAT_MOD(IE_REPUTATION);
2882 return FX_NOT_APPLIED; //needs testing
2885 // 0x6d --> see later
2887 // 0x6e works only in PST, reused for turning undead
2889 // 0x6f Item:CreateMagic
2891 static EffectRef fx_remove_item_ref={"Item:Remove",NULL,-1};
2893 int fx_create_magic_item (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2895 //charge count is incorrect
2896 target->inventory.SetSlotItemRes(fx->Resource, target->inventory.GetMagicSlot(),fx->Parameter1,fx->Parameter3,fx->Parameter4);
2897 //equip the weapon
2898 target->inventory.SetEquippedSlot(target->inventory.GetMagicSlot()-target->inventory.GetWeaponSlot(), 0);
2899 if ((fx->TimingMode&0xff) == FX_DURATION_INSTANT_LIMITED) {
2900 //if this effect has expiration, then it will remain as a remove_item
2901 //on the effect queue, inheriting all the parameters
2902 fx->Opcode=EffectQueue::ResolveEffect(fx_remove_item_ref);
2903 fx->TimingMode=FX_DURATION_DELAY_PERMANENT;
2904 return FX_APPLIED;
2906 return FX_NOT_APPLIED;
2909 // 0x70 Item:Remove
2910 int fx_remove_item (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2912 //will destroy the first item
2913 if (target->inventory.DestroyItem(fx->Resource,0,1)) {
2914 target->ReinitQuickSlots();
2916 return FX_NOT_APPLIED;
2919 // 0x71 Item:Equip
2920 int fx_equip_item (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2922 int eff = core->QuerySlotEffects( fx->Parameter2 );
2923 switch(eff) {
2924 case SLOT_EFFECT_NONE:
2925 case SLOT_EFFECT_MELEE:
2926 target->inventory.SetEquippedSlot( fx->Parameter2, fx->Parameter1 );
2927 break;
2928 default:
2929 target->inventory.EquipItem( fx->Parameter2 );
2930 break;
2932 target->ReinitQuickSlots();
2933 return FX_NOT_APPLIED;
2936 // 0x72 Dither
2937 int fx_dither (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
2939 if (0) printf( "fx_dither (%2d): Value: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
2940 //this effect doesn't work in any engine versions
2941 return FX_NOT_APPLIED;
2944 // 0x73 DetectAlignment
2945 //gemrb extension: chaotic/lawful detection
2946 int fx_detect_alignment (Scriptable* /*Owner*/, Actor* target, Effect* fx)
2948 ieDword msk;
2949 ieDword stat;
2951 if (fx->Parameter2<3) {
2952 //0,1,2 -> 1,2,3
2953 msk = fx->Parameter2+1;
2954 stat = target->GetStat(IE_ALIGNMENT)&AL_GE_MASK;
2956 else {
2957 //3,4,5 -> 0x10, 0x20, 0x30
2958 msk = (fx->Parameter2-2)<<4;
2959 stat = target->GetStat(IE_ALIGNMENT)&AL_LC_MASK;
2961 if (stat != msk) return FX_NOT_APPLIED;
2963 ieDword color = fx->Parameter1;
2964 switch (msk) {
2965 case AL_EVIL:
2966 if (!color) color = 0xff0000;
2967 displaymsg->DisplayConstantStringName(STR_EVIL, color, target);
2968 //glow red
2969 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0xff, 0, 0, 0);
2970 break;
2971 case AL_GOOD:
2972 if (!color) color = 0xff00;
2973 displaymsg->DisplayConstantStringName(STR_GOOD, color, target);
2974 //glow green
2975 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0, 0xff, 0, 0);
2976 break;
2977 case AL_GE_NEUTRAL:
2978 if (!color) color = 0xff;
2979 displaymsg->DisplayConstantStringName(STR_GE_NEUTRAL, color, target);
2980 //glow blue
2981 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0, 0, 0xff, 0);
2982 break;
2983 case AL_CHAOTIC:
2984 if (!color) color = 0xff00ff;
2985 displaymsg->DisplayConstantStringName(STR_CHAOTIC, color, target);
2986 //glow purple
2987 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0xff, 0, 0xff, 0);
2988 break;
2989 case AL_LAWFUL:
2990 if (!color) color = 0xffffff;
2991 displaymsg->DisplayConstantStringName(STR_LAWFUL, color, target);
2992 //glow white
2993 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0xff, 0xff, 0xff, 0);
2994 break;
2995 case AL_LC_NEUTRAL:
2996 if (!color) color = 0xff;
2997 displaymsg->DisplayConstantStringName(STR_LC_NEUTRAL, color, target);
2998 //glow blue
2999 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0, 0, 0xff, 0);
3000 break;
3002 return FX_NOT_APPLIED;
3005 // 0x74 Cure:Invisible2 (see 0x2f)
3007 // 0x75 Reveal:Area
3008 // 0 reveal whole area
3009 // 1 reveal area in pattern
3010 int fx_reveal_area (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3012 if (0) printf( "fx_reveal_area (%2d): Value: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3013 Map *map = target->GetCurrentArea();
3014 if (!map) {
3015 return FX_APPLIED;
3018 if (fx->Parameter2) {
3019 map->Explore(fx->Parameter1);
3020 } else {
3021 map->Explore(-1);
3023 return FX_NOT_APPLIED;
3026 // 0x76 Reveal:Creatures
3027 int fx_reveal_creatures (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
3029 if (0) printf( "fx_reveal_creatures (%2d): Value: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3030 //reveals creatures (not working in original IE)
3031 return FX_NOT_APPLIED;
3034 // 0x77 MirrorImage
3035 static EffectRef fx_mirror_image_modifier_ref={"MirrorImageModifier",NULL,-1};
3037 int fx_mirror_image (Scriptable* Owner, Actor* target, Effect* fx)
3039 if (0) printf( "fx_mirror_image (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3040 ieDword images;
3042 if (fx->Parameter2) {
3043 images = 1; //reflection
3045 else {
3046 images = core->Roll(1, fx->Parameter1, 0); //mirror image
3049 Effect *fx2 = target->fxqueue.HasEffect(fx_mirror_image_modifier_ref);
3050 if (fx2) {
3051 //update old effect with our numbers if our numbers are more
3052 if (fx2->Parameter1<images) {
3053 fx2->Parameter1=images;
3055 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) {
3056 fx2->TimingMode = FX_DURATION_INSTANT_PERMANENT;
3058 return FX_NOT_APPLIED;
3060 fx->Opcode = EffectQueue::ResolveEffect(fx_mirror_image_modifier_ref);
3061 fx->Parameter1=images;
3062 //parameter2 could be 0 or 1 (mirror image or reflection)
3063 //execute the translated effect
3064 return fx_mirror_image_modifier(Owner, target, fx);
3067 // 0x78 Protection:Weapons
3068 int fx_immune_to_weapon (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
3070 if (0) printf( "fx_immune_to_weapon (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3071 if (!fx->FirstApply) return FX_APPLIED;
3073 int level;
3074 ieDword mask, value;
3076 level = -1;
3077 mask = 0;
3078 value = 0;
3079 switch(fx->Parameter2) {
3080 case 0: //enchantment level
3081 level = fx->Parameter1;
3082 break;
3083 case 1: //all magical weapons
3084 value = IE_INV_ITEM_MAGICAL;
3085 //fallthrough
3086 case 2: //all nonmagical weapons
3087 mask = IE_INV_ITEM_MAGICAL;
3088 break;
3089 case 3: //all silver weapons
3090 value = IE_INV_ITEM_SILVER;
3091 //fallthrough
3092 case 4: //all non silver weapons
3093 mask = IE_INV_ITEM_SILVER;
3094 break;
3095 case 5:
3096 value = IE_INV_ITEM_SILVER;
3097 mask = IE_INV_ITEM_SILVER;
3098 level = 0;
3099 break;
3100 case 6: //all twohanded
3101 value = IE_INV_ITEM_TWOHANDED;
3102 //fallthrough
3103 case 7: //all not twohanded
3104 mask = IE_INV_ITEM_TWOHANDED;
3105 break;
3106 case 8: //all twohanded
3107 value = IE_INV_ITEM_CURSED;
3108 //fallthrough
3109 case 9: //all not twohanded
3110 mask = IE_INV_ITEM_CURSED;
3111 break;
3112 case 10: //all twohanded
3113 value = IE_INV_ITEM_COLDIRON;
3114 //fallthrough
3115 case 11: //all not twohanded
3116 mask = IE_INV_ITEM_COLDIRON;
3117 break;
3118 case 12:
3119 mask = fx->Parameter1;
3120 case 13:
3121 value = fx->Parameter1;
3122 break;
3123 default:;
3126 fx->Parameter1 = (ieDword) level; //putting the corrected value back
3127 fx->Parameter3 = mask;
3128 fx->Parameter4 = value;
3129 return FX_APPLIED;
3132 // 0x79 VisualAnimationEffect (unknown)
3133 int fx_visual_animation_effect (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
3135 //this is an unknown effect
3136 if (0) printf( "fx_visual_animation_effect (%2d)\n", fx->Opcode );
3137 return FX_NOT_APPLIED;
3140 // 0x7a Item:CreateInventory
3141 static EffectRef fx_remove_inventory_item_ref={"Item:RemoveInventory",NULL,-1};
3143 int fx_create_inventory_item (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3145 if (0) printf( "fx_create_inventory_item (%2d)\n", fx->Opcode );
3146 target->inventory.AddSlotItemRes( fx->Resource, SLOT_ONLYINVENTORY, fx->Parameter1, fx->Parameter3, fx->Parameter4 );
3147 if ((fx->TimingMode&0xff) == FX_DURATION_INSTANT_LIMITED) {
3148 //if this effect has expiration, then it will remain as a remove_item
3149 //on the effect queue, inheriting all the parameters
3150 fx->Opcode=EffectQueue::ResolveEffect(fx_remove_inventory_item_ref);
3151 fx->TimingMode=FX_DURATION_DELAY_PERMANENT;
3152 return FX_APPLIED;
3154 return FX_NOT_APPLIED;
3157 // 0x7b Item:RemoveInventory
3158 int fx_remove_inventory_item (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3160 if (0) printf( "fx_remove_inventory_item (%2d)\n", fx->Opcode );
3161 //FIXME: now equipped items are only wielded weapons
3162 //why would it not let equipped items to be destructed?
3163 target->inventory.DestroyItem(fx->Resource,IE_INV_ITEM_EQUIPPED,1);
3164 return FX_NOT_APPLIED;
3167 // 0x7c DimensionDoor
3168 // iwd2 has several options
3169 int fx_dimension_door (Scriptable* Owner, Actor* target, Effect* fx)
3171 if (0) printf( "fx_dimension_door (%2d) Type:%d\n", fx->Opcode, fx->Parameter2 );
3172 Point p;
3174 switch(fx->Parameter2)
3176 case 0: //target to point
3177 p.x=fx->PosX;
3178 p.y=fx->PosY;
3179 break;
3180 case 1: //owner to target
3181 if (Owner->Type!=ST_ACTOR) {
3182 return FX_NOT_APPLIED;
3184 p=target->Pos;
3185 target = (Actor *) Owner;
3186 break;
3187 case 2: //target to saved location
3188 p.x=STAT_GET(IE_SAVEDXPOS);
3189 p.x=STAT_GET(IE_SAVEDYPOS);
3190 target->SetOrientation(STAT_GET(IE_SAVEDFACE), false);
3191 break;
3192 case 3: //owner swapped with target
3193 if (Owner->Type!=ST_ACTOR) {
3194 return FX_NOT_APPLIED;
3196 p=target->Pos;
3197 target->SetPosition(Owner->Pos, true, 0);
3198 target = (Actor *) Owner;
3199 break;
3201 target->SetPosition(p, true, 0 );
3202 return FX_NOT_APPLIED;
3205 // 0x7d Unlock
3206 int fx_knock (Scriptable* Owner, Actor* /*target*/, Effect* fx)
3208 if (0) printf( "fx_knock (%2d) [%d.%d]\n", fx->Opcode, fx->PosX, fx->PosY );
3209 Map *map = Owner->GetCurrentArea();
3210 Point p(fx->PosX, fx->PosY);
3211 Door *door = map->TMap->GetDoorByPosition(p);
3212 if (door) {
3213 if (door->LockDifficulty<100) {
3214 door->SetDoorLocked(false, true);
3216 return FX_NOT_APPLIED;
3218 Container *container = map->TMap->GetContainerByPosition(p);
3219 if (container) {
3220 if(container->LockDifficulty<100) {
3221 container->SetContainerLocked(false);
3223 return FX_NOT_APPLIED;
3225 return FX_NOT_APPLIED;
3228 // 0x7e MovementRateModifier
3229 // 0xb0 MovementRateModifier2
3230 int fx_movement_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3232 if (0) printf( "fx_movement_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3234 //iwd2 freeaction disables only 0xb0, who cares
3235 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
3236 //iwd2 aegis doesn't protect against grease/acid fog slowness, but that is
3237 //definitely a bug
3238 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
3240 STAT_MOD(IE_MOVEMENTRATE);
3241 return FX_APPLIED;
3244 #define FX_MS 10
3245 static const ieResRef monster_summoning_2da[FX_MS]={"MONSUM01","MONSUM02","MONSUM03",
3246 "ANISUM01","ANISUM02", "MONSUM01", "MONSUM02","MONSUM03","ANISUM01","ANISUM02"};
3248 // 0x7f MonsterSummoning
3249 int fx_monster_summoning (Scriptable* Owner, Actor* target, Effect* fx)
3251 if (0) printf( "fx_monster_summoning (%2d): Number: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3252 //check the summoning limit?
3253 if (!Owner) {
3254 return FX_NOT_APPLIED;
3257 if (!Owner->GetCurrentArea()) {
3258 return FX_APPLIED;
3261 //get monster resref from 2da determined by fx->Resource or fx->Parameter2
3262 ieResRef monster;
3263 ieResRef hit;
3264 ieResRef areahit;
3265 int level = fx->Parameter1;
3267 if (fx->Parameter2>=FX_MS) {
3268 strnuprcpy(monster,fx->Resource,8);
3269 strnuprcpy(hit,fx->Resource2,8);
3270 strnuprcpy(areahit,fx->Resource3,8);
3271 } else {
3272 core->GetResRefFrom2DA(monster_summoning_2da[fx->Parameter2], monster, hit, areahit);
3274 if (!hit[0]) {
3275 strnuprcpy(hit,fx->Resource2,8);
3277 if (!areahit[0]) {
3278 strnuprcpy(areahit,fx->Resource3,8);
3282 //the monster should appear near the effect position
3283 Point p(fx->PosX, fx->PosY);
3285 Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
3286 core->SummonCreature(monster, hit, Owner, target, p, fx->Parameter2/5, level, newfx);
3287 delete newfx;
3288 return FX_NOT_APPLIED;
3291 // 0x80 State:Confused
3292 int fx_set_confused_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3294 if (0) printf( "fx_set_confused_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3296 if (target->HasSpellState(SS_BLOODRAGE)) {
3297 return FX_NOT_APPLIED;
3300 if (fx->TimingMode==FX_DURATION_DELAY_PERMANENT) {
3301 BASE_STATE_SET( STATE_CONFUSED );
3302 } else {
3303 STATE_SET( STATE_CONFUSED );
3305 //NOTE: iwd2 is also unable to display the portrait icon
3306 //for permanent confusion
3307 if (enhanced_effects) {
3308 target->AddPortraitIcon(PI_CONFUSED);
3310 return FX_PERMANENT;
3313 // 0x81 AidNonCumulative
3314 int fx_set_aid_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3316 if (0) printf( "fx_set_aid_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3317 if (!fx->Parameter2) {
3318 fx->Parameter2=core->Roll(fx->Parameter1,8,0);
3320 if (STATE_GET (STATE_AID) ) //aid is non cumulative
3321 return FX_NOT_APPLIED;
3322 STATE_SET( STATE_AID );
3323 target->SetSpellState(SS_AID);
3324 STAT_ADD( IE_MAXHITPOINTS, fx->Parameter2);
3325 //This better happens after increasing maxhitpoints
3326 if (fx->FirstApply) {
3327 BASE_ADD( IE_HITPOINTS, fx->Parameter1);
3329 STAT_ADD( IE_SAVEVSDEATH, fx->Parameter1);
3330 STAT_ADD( IE_SAVEVSWANDS, fx->Parameter1);
3331 STAT_ADD( IE_SAVEVSPOLY, fx->Parameter1);
3332 STAT_ADD( IE_SAVEVSBREATH, fx->Parameter1);
3333 STAT_ADD( IE_SAVEVSSPELL, fx->Parameter1);
3334 //bless effect too?
3335 STAT_ADD( IE_TOHIT, fx->Parameter1);
3336 STAT_ADD( IE_MORALEBREAK, fx->Parameter1);
3337 if (enhanced_effects) {
3338 target->AddPortraitIcon(PI_AID);
3339 target->SetColorMod(0xff, RGBModifier::ADD, 30, 50, 50, 50);
3341 return FX_APPLIED;
3344 // 0x82 BlessNonCumulative
3346 static EffectRef fx_bane_ref={"Bane",NULL,-1};
3348 int fx_set_bless_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3350 if (0) printf( "fx_set_bless_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3352 if (STATE_GET (STATE_BLESS) ) //bless is non cumulative
3353 return FX_NOT_APPLIED;
3355 //do this once
3356 target->fxqueue.RemoveAllEffects(fx_bane_ref);
3358 STATE_SET( STATE_BLESS );
3359 target->SetSpellState(SS_BLESS);
3360 STAT_ADD( IE_TOHIT, fx->Parameter1);
3361 STAT_ADD( IE_MORALEBREAK, fx->Parameter1);
3362 if (enhanced_effects) {
3363 target->AddPortraitIcon(PI_BLESS);
3364 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0xc0, 0x80, 0);
3366 return FX_APPLIED;
3368 // 0x83 ChantNonCumulative
3369 int fx_set_chant_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3371 if (0) printf( "fx_set_chant_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3373 if (STATE_GET (STATE_CHANT) ) //chant is non cumulative
3374 return FX_NOT_APPLIED;
3375 STATE_SET( STATE_CHANT );
3376 target->SetSpellState(SS_GOODCHANT);
3377 STAT_ADD( IE_LUCK, fx->Parameter1 );
3378 return FX_APPLIED;
3381 // 0x84 HolyNonCumulative
3382 int fx_set_holy_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3384 if (0) printf( "fx_set_holy_state (%2d): Modifier: %d\n", fx->Opcode, fx->Parameter1 );
3386 if (STATE_GET (STATE_HOLY) ) //holy power is non cumulative
3387 return FX_NOT_APPLIED;
3388 STATE_SET( STATE_HOLY );
3389 //setting the spell state to be compatible with iwd2
3390 target->SetSpellState(SS_HOLYMIGHT);
3391 STAT_ADD( IE_STR, fx->Parameter1);
3392 STAT_ADD( IE_CON, fx->Parameter1);
3393 STAT_ADD( IE_DEX, fx->Parameter1);
3394 if (enhanced_effects) {
3395 target->AddPortraitIcon(PI_HOLY);
3396 target->SetColorMod(0xff, RGBModifier::ADD, 30, 0x80, 0x80, 0x80);
3398 return FX_APPLIED;
3401 // 0x85 LuckNonCumulative
3402 int fx_luck_non_cumulative (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3404 if (0) printf( "fx_luck_non_cumulative (%2d): Modifier: %d\n", fx->Opcode, fx->Parameter1);
3406 if (STATE_GET (STATE_LUCK) ) //this luck is non cumulative
3407 return FX_NOT_APPLIED;
3408 STATE_SET( STATE_LUCK );
3409 target->SetSpellState(SS_LUCK);
3410 STAT_ADD( IE_LUCK, fx->Parameter1 );
3411 STAT_ADD( IE_DAMAGELUCK, fx->Parameter1 );
3412 return FX_APPLIED;
3415 // 0x85 LuckCumulative (iwd2)
3416 int fx_luck_cumulative (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3418 if (0) printf( "fx_luck_cumulative (%2d): Modifier: %d\n", fx->Opcode, fx->Parameter1);
3420 target->SetSpellState(SS_LUCK);
3421 STAT_ADD( IE_LUCK, fx->Parameter1 );
3422 STAT_ADD( IE_DAMAGELUCK, fx->Parameter1 );
3423 return FX_APPLIED;
3426 // 0x86 State:Petrification
3427 int fx_set_petrified_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3429 if (0) printf( "fx_set_petrified_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3431 BASE_STATE_SET( STATE_PETRIFIED );
3432 return FX_NOT_APPLIED; //permanent effect
3435 // 0x87 Polymorph
3436 static EffectRef fx_polymorph_ref={"Polymorph",NULL,-1};
3438 void CopyPolymorphStats(Actor *source, Actor *target)
3440 int i;
3442 if(!polymorph_stats) {
3443 AutoTable tab("polystat");
3444 if (!tab) {
3445 polymorph_stats = (int *) malloc(0);
3446 polystatcount=0;
3447 return;
3449 polystatcount = tab->GetRowCount();
3450 polymorph_stats=(int *) malloc(sizeof(int)*polystatcount);
3451 for (i=0;i<polystatcount;i++) {
3452 polymorph_stats[i]=core->TranslateStat(tab->QueryField(i,0));
3456 //copy polymorphed stats, no need of using STAT_SET, because the stats
3457 //are copied from a consistent state
3458 for(i=0;i<polystatcount;i++) {
3459 target->Modified[polymorph_stats[i]]=source->Modified[polymorph_stats[i]];
3463 int fx_polymorph (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3465 if (0) printf( "fx_set_polymorph_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3467 if (!gamedata->Exists(fx->Resource,IE_CRE_CLASS_ID)) {
3468 //kill all polymorph effects
3469 target->fxqueue.RemoveAllEffectsWithParam(fx_polymorph_ref, fx->Parameter2);
3470 //destroy the magic item slot
3471 target->inventory.RemoveItem(target->inventory.GetMagicSlot() );
3472 return FX_NOT_APPLIED;
3475 //FIXME:
3476 //This pointer should be cached, or we are in deep trouble
3477 Actor *newCreature = gamedata->GetCreature(fx->Resource,0);
3479 //I don't know how could this happen, existance of the resource was already checked
3480 if (!newCreature) {
3481 return FX_NOT_APPLIED;
3484 //copy the animation ID; never resets back! shapeshift to natural doesn't work either
3485 //target->SetAnimationID( newCreature->GetStat(IE_ANIMATION_ID) );
3486 //TODO: also change the inventory paper doll
3488 //copy all polymorphed stats
3489 if(fx->Parameter2) {
3490 STAT_SET( IE_POLYMORPHED, 1 );
3491 //FIXME: of course, the first parameter should be the creature we copy
3492 CopyPolymorphStats(newCreature, target);
3495 //FIXME:
3496 //Be careful when this became a cached pointer
3497 delete newCreature;
3498 return FX_APPLIED;
3501 // 0x88 ForceVisible
3502 int fx_force_visible (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3504 if (0) printf( "fx_force_visible (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3506 BASE_STATE_CURE(STATE_INVISIBLE);
3507 target->fxqueue.RemoveAllEffectsWithParam(fx_set_invisible_state_ref,0);
3508 target->fxqueue.RemoveAllEffectsWithParam(fx_set_invisible_state_ref,2);
3509 return FX_NOT_APPLIED;
3512 // 0x89 ChantBadNonCumulative
3513 int fx_set_chantbad_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3515 if (0) printf( "fx_set_chantbad_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3517 if (STATE_GET (STATE_CHANTBAD) ) //chant is non cumulative
3518 return FX_NOT_APPLIED;
3519 STATE_SET( STATE_CHANTBAD );
3520 target->SetSpellState(SS_BADCHANT);
3521 STAT_SUB( IE_LUCK, fx->Parameter1 );
3522 return FX_APPLIED;
3525 // 0x8A AnimationStateChange
3526 int fx_animation_stance (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3528 if (0) printf( "fx_animation_stance (%2d): Stance: %d\n", fx->Opcode, fx->Parameter2 );
3530 //this effect works only on living actors
3531 if ( !STATE_GET(STATE_DEAD) ) {
3532 target->SetStance(fx->Parameter2);
3534 return FX_NOT_APPLIED;
3537 // 0x8B DisplayString
3538 // gemrb extension: rgb colour for displaystring
3539 static EffectRef fx_protection_from_display_string_ref={"Protection:String",NULL,-1};
3541 int fx_display_string (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3543 if (0) printf( "fx_display_string (%2d): StrRef: %d\n", fx->Opcode, fx->Parameter1 );
3544 if (!target->fxqueue.HasEffectWithParamPair(fx_protection_from_display_string_ref, fx->Parameter1, 0) ) {
3545 displaymsg->DisplayStringName(fx->Parameter1, fx->Parameter2?fx->Parameter2:0xffffff, target, IE_STR_SOUND|IE_STR_SPEECH);
3547 return FX_NOT_APPLIED;
3550 // 0x8c CastingGlow
3551 static const int ypos_by_direction[16]={10,10,10,0,-10,-10,-10,-10,-10,-10,-10,-10,0,10,10,10};
3552 static const int xpos_by_direction[16]={0,-10,-12,-14,-16,-14,-12,-10,0,10,12,14,16,14,12,10};
3554 int fx_casting_glow (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3556 if (0) printf( "fx_casting_glow (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
3557 if (cgcount<0) {
3558 cgcount = core->ReadResRefTable("cgtable",casting_glows);
3560 //remove effect if map is not loaded
3561 Map *map = target->GetCurrentArea();
3562 if (!map) {
3563 return FX_NOT_APPLIED;
3566 if (fx->Parameter2<(ieDword) cgcount) {
3567 ScriptedAnimation *sca = gamedata->GetScriptedAnimation(casting_glows[fx->Parameter2], false);
3568 //remove effect if animation doesn't exist
3569 if (!sca) {
3570 return FX_NOT_APPLIED;
3572 //12 is just an approximate value to set the height of the casting glow
3573 //based on the avatar's size
3574 int heightmod = target->GetAnims()->GetCircleSize()*12;
3575 sca->XPos+=fx->PosX+xpos_by_direction[target->GetOrientation()];
3576 sca->YPos+=fx->PosY+ypos_by_direction[target->GetOrientation()];
3577 sca->ZPos+=heightmod;
3578 sca->SetBlend();
3579 if (fx->Duration) {
3580 sca->SetDefaultDuration(fx->Duration-core->GetGame()->GameTime);
3581 } else {
3582 sca->SetDefaultDuration(10000);
3584 map->AddVVCell(sca);
3586 return FX_NOT_APPLIED;
3589 //0x8d VisualSpellHit
3590 int fx_visual_spell_hit (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3592 if (0) printf( "fx_visual_spell_hit (%2d): Target: %d Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3593 if (shcount<0) {
3594 shcount = core->ReadResRefTable("shtable",spell_hits);
3596 //remove effect if map is not loaded
3597 Map *map = target->GetCurrentArea();
3598 if (!map) {
3599 return FX_NOT_APPLIED;
3601 if (fx->Parameter2<(ieDword) shcount) {
3602 ScriptedAnimation *sca = gamedata->GetScriptedAnimation(spell_hits[fx->Parameter2], false);
3603 //remove effect if animation doesn't exist
3604 if (!sca) {
3605 return FX_NOT_APPLIED;
3607 if (fx->Parameter1) {
3608 sca->XPos+=target->Pos.x;
3609 sca->YPos+=target->Pos.y;
3610 } else {
3611 sca->XPos+=fx->PosX;
3612 sca->YPos+=fx->PosY;
3614 if (fx->Parameter2<32) {
3615 int tmp = fx->Parameter2>>2;
3616 if (tmp) {
3617 sca->SetFullPalette(tmp);
3620 sca->SetBlend();
3621 sca->PlayOnce();
3622 map->AddVVCell(sca);
3623 } else {
3624 printf("fx_visual_spell_hit: Unhandled Type: %d\n", fx->Parameter2);
3626 return FX_NOT_APPLIED;
3629 //0x8e Icon:Display
3630 int fx_display_portrait_icon (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3632 if (0) printf( "fx_display_string (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
3633 target->AddPortraitIcon(fx->Parameter2);
3634 return FX_APPLIED;
3637 //0x8f Item:CreateInSlot
3638 int fx_create_item_in_slot (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3640 if (0) printf( "fx_create_item_in_slot (%2d): Button: %d\n", fx->Opcode, fx->Parameter2 );
3641 //create item and set it in target's slot
3642 target->inventory.SetSlotItemRes( fx->Resource, core->QuerySlot(fx->Parameter2), fx->Parameter1, fx->Parameter3, fx->Parameter4 );
3643 if ((fx->TimingMode&0xff) == FX_DURATION_INSTANT_LIMITED) {
3644 //convert it to a destroy item
3645 fx->Opcode=EffectQueue::ResolveEffect(fx_remove_item_ref);
3646 fx->TimingMode=FX_DURATION_DELAY_PERMANENT;
3647 return FX_APPLIED;
3649 return FX_NOT_APPLIED;
3652 // 0x90 DisableButton
3653 // different in iwd2 and the rest (maybe also in how: 0-7?)
3654 int fx_disable_button (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3656 if (0) printf( "fx_disable_button (%2d): Button: %d\n", fx->Opcode, fx->Parameter2 );
3658 // iwd2 has a flexible action bar, so there are more possible parameter values
3659 // only values 0-5 match the bg2 constants (which map to ACT_*)
3660 // FIXME: support disabling all iwd2 buttons
3661 if (target->spellbook.IsIWDSpellBook()) {
3662 if (fx->Parameter2 < 6) STAT_BIT_OR( IE_DISABLEDBUTTON, 1<<fx->Parameter2 );
3663 } else {
3664 STAT_BIT_OR( IE_DISABLEDBUTTON, 1<<fx->Parameter2 );
3667 if (target->InParty && fx->FirstApply) {
3668 core->SetEventFlag(EF_ACTION);
3670 return FX_APPLIED;
3673 //0x91 DisableSpellCasting
3674 //bg2: 0 - mage, 1 - cleric, 2 - innate
3675 //iwd2: 0 - all, 1 - mage+cleric, 2 - mage, 3 - cleric , 4 - innate
3676 int fx_disable_spellcasting (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3678 if (0) printf( "fx_disable_spellcasting (%2d): Button: %d\n", fx->Opcode, fx->Parameter2 );
3680 if (!fx->FirstApply) {
3681 return FX_APPLIED;
3683 bool display_warning = false;
3685 //IWD2 Style spellbook
3686 if (target->spellbook.IsIWDSpellBook()) {
3687 switch(fx->Parameter2) {
3688 case 0: // all
3689 case 1: // mage and cleric
3690 case 2: // mage
3691 if (target->spellbook.GetKnownSpellsCount(IE_IWD2_SPELL_BARD, 0)) display_warning = true;
3692 if (target->spellbook.GetKnownSpellsCount(IE_IWD2_SPELL_SORCEROR, 0)) display_warning = true;
3693 if (target->spellbook.GetKnownSpellsCount(IE_IWD2_SPELL_WIZARD, 0)) display_warning = true;
3694 break;
3696 } else { // bg2
3697 if (fx->Parameter2 == 0)
3698 if (target->spellbook.GetKnownSpellsCount(IE_SPELL_TYPE_WIZARD, 0)) display_warning = true;
3700 if (target->InParty && display_warning) {
3701 displaymsg->DisplayConstantStringName(STR_DISABLEDMAGE, 0xff0000, target);
3702 core->SetEventFlag(EF_ACTION);
3704 return FX_APPLIED;
3707 //0x92 Spell:Cast
3708 int fx_cast_spell (Scriptable* Owner, Actor* target, Effect* fx)
3710 if (0) printf( "fx_cast_spell (%2d): Resource:%s Mode: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
3711 if (fx->Parameter2) {
3712 //apply spell on target
3713 core->ApplySpell(fx->Resource, target, Owner, fx->Power);
3714 } else {
3715 //cast spell on target
3716 Owner->CastSpell(fx->Resource, target, false);
3717 //actually finish casting (if this is not good enough, use an action???)
3718 Owner->CastSpellEnd(fx->Resource);
3720 return FX_NOT_APPLIED;
3723 // 0x93 Spell:Learn
3724 int fx_learn_spell (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3726 if (0) printf( "fx_learn_spell (%2d): Resource:%s Mode: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
3727 //parameter1 is unused, gemrb lets you to make it not give XP
3728 //probably we should also let this via a game flag if we want
3729 //full compatibility with bg1
3730 target->LearnSpell(fx->Resource, fx->Parameter2^LS_ADDXP);
3731 return FX_NOT_APPLIED;
3733 // 0x94 Spell:CastSpellPoint
3734 int fx_cast_spell_point (Scriptable* Owner, Actor* target, Effect* fx)
3736 if (0) printf( "fx_cast_spell_point (%2d): Resource:%s Mode: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
3737 Owner->CastSpellPoint(fx->Resource, target->Pos, false);
3738 //actually finish casting (if this is not good enough, use an action???)
3739 Owner->CastSpellPointEnd(fx->Resource);
3740 return FX_NOT_APPLIED;
3743 // 0x95 Identify
3744 int fx_identify (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3746 if (0) printf( "fx_identify (%2d): Resource:%s Mode: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
3747 if (target->InParty) {
3748 BASE_SET (IE_IDENTIFYMODE, 1);
3749 core->SetEventFlag(EF_IDENTIFY);
3751 return FX_NOT_APPLIED;
3753 // 0x96 FindTraps
3754 // (actually, in bg2 the effect targets area objects and the range is implemented
3755 // by the inareans projectile) - inanimate, area, no sprite
3756 // TODO: effects should target inanimates using different code
3757 int fx_find_traps (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3759 if (0) printf( "fx_find_traps (%2d)\n", fx->Opcode );
3760 //reveal trapped containers, doors, triggers that are in the visible range
3761 ieDword range = target->GetStat(IE_VISUALRANGE)*10;
3762 ieDword skill;
3764 if (fx->Parameter2 == 0)
3765 skill = 256; //always works
3766 else
3767 skill = target->GetStat(IE_TRAPS); //based on skill
3769 TileMap *TMap = target->GetCurrentArea()->TMap;
3771 int Count = 0;
3772 while (true) {
3773 Door* door = TMap->GetDoor( Count++ );
3774 if (!door)
3775 break;
3777 //not trapped
3778 if (!door->Scripts[0]) {
3779 continue;
3781 //not detectable
3782 if (!(door->Flags&DOOR_DETECTABLE)) {
3783 continue;
3786 if (Distance(door->Pos, target->Pos)<range) {
3787 //when was door trap noticed
3788 door->DetectTrap(skill);
3789 // door->TrapDetected = 1;
3793 Count = 0;
3794 while (true) {
3795 Container* container = TMap->GetContainer( Count++ );
3796 if (!container)
3797 break;
3798 if (Distance(container->Pos, target->Pos)<range) {
3799 //when was door trap noticed
3800 container->DetectTrap(skill);
3805 Count = 0;
3806 while (true) {
3807 InfoPoint* trap = TMap->GetInfoPoint( Count++ );
3808 if (!trap)
3809 break;
3810 if (Distance(trap->Pos, target->Pos)<range) {
3811 //when was door trap noticed
3812 trap->DetectTrap(skill);
3816 return FX_NOT_APPLIED;
3818 // 0x97 ReplaceCreature
3819 int fx_replace_creature (Scriptable* Owner, Actor* target, Effect *fx)
3821 if (0) printf( "fx_replace_creature (%2d): Resource: %s\n", fx->Opcode, fx->Resource );
3823 //this safeguard exists in the original engine too
3824 if (!gamedata->Exists(fx->Resource,IE_CRE_CLASS_ID)) {
3825 return FX_NOT_APPLIED;
3828 //the monster should appear near the effect position? (unsure)
3829 Point p(fx->PosX, fx->PosY);
3831 //remove old creature
3832 switch(fx->Parameter2) {
3833 case 0: //remove silently
3834 target->DestroySelf();
3835 break;
3836 case 1: //chunky death
3837 target->NewBase(IE_HITPOINTS,(ieDword) -100, MOD_ABSOLUTE);
3838 target->Die(Owner);
3839 break;
3840 case 2: //normal death
3841 target->Die(Owner);
3842 break;
3843 default:;
3845 //create replacement; should we be passing the target instead of NULL?
3846 //noooo, don't unsummon replacement creatures! - fuzzie
3847 //Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
3848 core->SummonCreature(fx->Resource, fx->Resource2, Owner, NULL,p, EAM_DEFAULT,-1, NULL, 0);
3849 //delete newfx;
3850 return FX_NOT_APPLIED;
3853 // 0x98 PlayMovie
3854 int fx_play_movie (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
3856 if (0) printf( "fx_play_movie (%2d): Resource: %s\n", fx->Opcode, fx->Resource );
3857 core->PlayMovie (fx->Resource);
3858 return FX_NOT_APPLIED;
3860 // 0x99 Overlay:Sanctuary
3861 #define ICE_GRADIENT 71
3863 static const ieDword fullwhite[7]={ICE_GRADIENT,ICE_GRADIENT,ICE_GRADIENT,ICE_GRADIENT,ICE_GRADIENT,ICE_GRADIENT,ICE_GRADIENT};
3865 int fx_set_sanctuary_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3867 //iwd and bg are a bit different, but we solve the whole stuff in a single opcode
3868 if (0) printf( "fx_set_sanctuary_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3869 if (!fx->Parameter2) {
3870 fx->Parameter2=1;
3872 //this effect needs the pcf run immediately
3873 STAT_SET_PCF( IE_SANCTUARY, fx->Parameter2);
3874 //a rare event, but this effect gives more in bg2 than in iwd2
3875 //so we use this flag
3876 if (!enhanced_effects)
3878 target->SetLockedPalette(fullwhite);
3880 return FX_APPLIED;
3883 // 0x9a Overlay:Entangle
3884 int fx_set_entangle_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3886 if (0) printf( "fx_set_entangle_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3888 //iwd2 effects that disable entangle
3889 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
3890 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
3892 if (!fx->Parameter2) {
3893 fx->Parameter2=1;
3895 STAT_SET_PCF( IE_ENTANGLE, fx->Parameter2);
3896 return FX_APPLIED;
3899 // 0x9b Overlay:MinorGlobe
3900 int fx_set_minorglobe_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3902 if (0) printf( "fx_set_minorglobe_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3903 //the resisted levels are stored in minor globe (bit 2-)
3904 //the globe effect is stored in the first bit
3905 STAT_BIT_OR_PCF( IE_MINORGLOBE, 1);
3906 return FX_APPLIED;
3909 // 0x9c Overlay:ShieldGlobe
3910 int fx_set_shieldglobe_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3912 if (0) printf( "fx_set_shieldglobe_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3913 STAT_SET_PCF( IE_SHIELDGLOBE, 1);
3914 return FX_APPLIED;
3917 // 0x9d Overlay:Web
3918 int fx_set_web_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3920 if (0) printf( "fx_set_web_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3922 //iwd2 effects that disable web
3923 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
3924 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
3926 target->SetSpellState(SS_WEB);
3927 //attack penalty in IWD2
3928 STAT_SET_PCF( IE_WEB, 1);
3929 STAT_SET(IE_MOVEMENTRATE, 0); //
3930 return FX_APPLIED;
3933 // 0x9e Overlay:Grease
3934 int fx_set_grease_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3936 if (0) printf( "fx_set_grease_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3938 //iwd2 effects that disable grease
3939 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
3940 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
3942 target->SetSpellState(SS_GREASE);
3943 STAT_SET_PCF( IE_GREASE, 1);
3944 //the movement rate is set by separate opcodes in all engines
3945 return FX_APPLIED;
3948 // 0x9f MirrorImageModifier
3949 int fx_mirror_image_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3951 if (0) printf( "fx_mirror_image_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 );
3952 if (STATE_GET(STATE_DEAD) ) {
3953 return FX_NOT_APPLIED;
3955 if (!fx->Parameter1) {
3956 return FX_NOT_APPLIED;
3958 STATE_SET( STATE_MIRROR );
3959 if (fx->Parameter2) {
3960 target->SetSpellState(SS_REFLECTION);
3961 } else {
3962 target->SetSpellState(SS_MIRRORIMAGE);
3964 //actually, there is no such stat in the original IE
3965 STAT_SET( IE_MIRRORIMAGES, fx->Parameter1);
3966 return FX_APPLIED;
3969 // 0xa0 Cure:Sanctuary
3970 static EffectRef fx_sanctuary_state_ref={"Overlay:Sanctuary",NULL,-1};
3972 int fx_cure_sanctuary_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3974 if (0) printf( "fx_cure_sanctuary_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3975 STAT_SET( IE_SANCTUARY, 0);
3976 target->fxqueue.RemoveAllEffects(fx_sanctuary_state_ref);
3977 return FX_NOT_APPLIED;
3980 // 0xa1 Cure:Panic
3981 static EffectRef fx_set_panic_state_ref={"State:Panic",NULL,-1};
3983 int fx_cure_panic_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3985 if (0) printf( "fx_cure_panic_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3986 BASE_STATE_CURE( STATE_PANIC );
3987 target->fxqueue.RemoveAllEffects(fx_set_panic_state_ref);
3988 return FX_NOT_APPLIED;
3991 // 0xa2 Cure:Hold
3992 static EffectRef fx_hold_creature_ref={"State:Hold",NULL,-1};
3994 int fx_cure_hold_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
3996 if (0) printf( "fx_cure_hold_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
3997 //note that this effect doesn't remove 185 (another hold effect)
3998 target->fxqueue.RemoveAllEffects( fx_hold_creature_ref );
3999 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_HELD);
4000 return FX_NOT_APPLIED;
4003 // 0xa3 FreeAction
4004 static EffectRef fx_movement_modifier_ref={"MovementRateModifier2",NULL,-1};
4006 int fx_cure_slow_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4008 if (0) printf( "fx_cure_slow_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4009 target->fxqueue.RemoveAllEffects( fx_movement_modifier_ref );
4010 // STATE_CURE( STATE_SLOWED );
4011 return FX_NOT_APPLIED;
4014 // 0xa4 Cure:Intoxication
4015 static EffectRef fx_intoxication_ref={"IntoxicationModifier",NULL,-1};
4017 int fx_cure_intoxication (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4019 if (0) printf( "fx_cure_intoxication (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4020 target->fxqueue.RemoveAllEffects( fx_intoxication_ref );
4021 BASE_SET(IE_INTOXICATION,0);
4022 return FX_NOT_APPLIED;
4025 // 0xa5 PauseTarget
4026 int fx_pause_target (Scriptable* /*Owner*/, Actor * target, Effect* fx)
4028 if (0) printf( "fx_pause_target (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4030 STAT_MOD( IE_CASTERHOLD );
4031 return FX_PERMANENT;
4034 // 0xa6 MagicResistanceModifier
4035 int fx_magic_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4037 if (0) printf( "fx_magic_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4039 STAT_MOD( IE_RESISTMAGIC );
4040 return FX_APPLIED;
4043 // 0xa7 MissileHitModifier
4044 int fx_missile_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4046 if (0) printf( "fx_missile_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4048 STAT_MOD( IE_MISSILEHITBONUS );
4049 return FX_APPLIED;
4052 // 0xa8 RemoveCreature
4053 // removes targeted creature
4054 // removes creature specified by resource key (gemrb extension)
4055 int fx_remove_creature (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4057 if (0) printf( "fx_remove_creature (%2d)\n", fx->Opcode);
4058 Map *map = target->GetCurrentArea();
4059 Actor *actor = target;
4061 if (fx->Resource[0]) {
4062 actor = map->GetActorByResource(fx->Resource);
4065 if (actor) {
4066 //play vvc effect over actor?
4067 actor->DestroySelf();
4069 return FX_NOT_APPLIED;
4072 // 0xa9 Icon:Disable
4073 int fx_disable_portrait_icon (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4075 if (0) printf( "fx_disable_portrait_icon (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4076 target->DisablePortraitIcon(fx->Parameter2);
4077 return FX_APPLIED;
4080 // 0xaa DamageAnimation
4081 int fx_damage_animation (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4083 if (0) printf( "fx_damage_animation (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4085 //Parameter1 is a gemrb extension
4086 target->PlayDamageAnimation(fx->Parameter2, !fx->Parameter1);
4087 return FX_NOT_APPLIED;
4090 // 0xab Spell:Add
4091 int fx_add_innate (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4093 if (0) printf( "fx_add_innate (%2d): Resource: %s Mode: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
4094 target->LearnSpell(fx->Resource, fx->Parameter2^LS_MEMO);
4095 //this is an instant, so it shouldn't stick
4096 return FX_NOT_APPLIED;
4099 // 0xac Spell:Remove
4100 //gemrb extension: deplete spell by resref
4101 int fx_remove_spell (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4103 if (0) printf( "fx_remove_spell (%2d): Resource: %s Type:%d\n", fx->Opcode, fx->Resource, fx->Parameter2);
4104 switch (fx->Parameter2) {
4105 default:
4106 target->spellbook.RemoveSpell(fx->Resource);
4107 break;
4108 case 1: //forget all spells of Resource
4109 do {} while(target->spellbook.HaveSpell( fx->Resource, HS_DEPLETE ));
4110 break;
4111 case 2: //forget x spells of resource
4112 while( fx->Parameter1--) {
4113 target->spellbook.HaveSpell( fx->Resource, HS_DEPLETE );
4115 break;
4117 //this is an instant, so it shouldn't stick
4118 return FX_NOT_APPLIED;
4121 // 0xad PoisonResistanceModifier
4122 int fx_poison_resistance_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4124 if (0) printf( "fx_poison_resistance_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4126 STAT_MOD( IE_RESISTPOISON );
4127 return FX_APPLIED;
4130 //0xae PlaySound
4131 int fx_playsound (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4133 if (0) printf( "fx_playsound (%s)", fx->Resource );
4134 //this is probably inaccurate
4135 if (target) {
4136 core->GetAudioDrv()->Play(fx->Resource, target->Pos.x, target->Pos.y);
4137 } else {
4138 core->GetAudioDrv()->Play(fx->Resource);
4140 //this is an instant, it shouldn't stick
4141 return FX_NOT_APPLIED;
4144 //0x6d State:Hold3
4145 //0xfb State:Hold4
4146 int fx_hold_creature_no_icon (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4148 if (0) printf( "fx_hold_creature_no_icon (%2d): Value: %d, IDS: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4150 //actually the original engine just skips this effect if the target is dead
4151 if ( STATE_GET(STATE_DEAD) ) {
4152 return FX_NOT_APPLIED;
4155 if (!EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
4156 //if the ids don't match, the effect doesn't stick
4157 return FX_NOT_APPLIED;
4159 target->SetSpellState(SS_HELD);
4160 STAT_SET( IE_HELD, 1);
4161 return FX_APPLIED;
4164 //0xaf State:Hold
4165 //0xb9 State:Hold2
4166 //(0x6d/0x1a8 for iwd2)
4167 int fx_hold_creature (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4169 if (0) printf( "fx_hold_creature (%2d): Value: %d, IDS: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4171 //actually the original engine just skips this effect if the target is dead
4172 if ( STATE_GET(STATE_DEAD) ) {
4173 return FX_NOT_APPLIED;
4176 //iwd2 free action or blood rage disables this effect
4177 if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED;
4178 if (target->HasSpellState(SS_BLOODRAGE)) return FX_NOT_APPLIED;
4179 if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED;
4181 if (!EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
4182 //if the ids don't match, the effect doesn't stick
4183 return FX_NOT_APPLIED;
4185 target->SetSpellState(SS_HELD);
4186 STAT_SET( IE_HELD, 1);
4187 target->AddPortraitIcon(PI_HELD);
4188 return FX_APPLIED;
4190 //0xb0 see: fx_movement_modifier
4192 //0xb1 ApplyEffect
4193 int fx_apply_effect (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4195 if (0) printf( "fx_apply_effect (%2d) %s", fx->Opcode, fx->Resource );
4197 //this effect executes a file effect in place of this effect
4198 //the file effect inherits the target and the timingmode, but gets
4199 //a new chance to roll percents
4200 int ret = FX_NOT_APPLIED;
4201 if (!target) {
4202 return ret;
4204 if (EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
4205 Point p(fx->PosX, fx->PosY);
4207 //apply effect, if the effect is a goner, then kill
4208 //this effect too
4209 Effect *newfx = core->GetEffect(fx->Resource, fx->Power, p);
4210 if (newfx) {
4211 Effect *myfx = new Effect;
4212 memcpy(myfx, newfx, sizeof(Effect));
4213 myfx->random_value = core->Roll(1,100,0);
4214 myfx->Target = FX_TARGET_PRESET;
4215 myfx->TimingMode = fx->TimingMode;
4216 myfx->Duration = fx->Duration;
4217 ret = target->fxqueue.ApplyEffect(target, myfx, fx->FirstApply);
4218 delete myfx;
4220 //newfx is a borrowed reference don't delete it
4222 return ret;
4225 //0xb2 hitbonus generic effect ToHitVsCreature
4226 //0xb3 damagebonus generic effect DamageVsCreature
4227 // b4 can't use item (resource) generic effect CantUseItem
4228 // b5 can't use itemtype (resource) generic effect CantUseItemType
4229 // b6 generic effect ApplyEffectItem
4230 // b7 generic effect ApplyEffectItemType
4231 // b8 DontJumpModifier
4232 int fx_dontjump_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4234 if (0) printf( "fx_dontjump_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4235 STAT_SET( IE_DONOTJUMP, fx->Parameter2 );
4236 return FX_APPLIED;
4239 //0xb9 see above: fx_hold_creature
4241 //0xba MoveToArea
4242 int fx_move_to_area (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4244 if (0) printf( "fx_move_to_area (%2d) %s", fx->Opcode, fx->Resource );
4245 //delay effect until the target has finished the previous move to an area
4246 //hopefully this fixes an evil bug
4247 Map *map = target->GetCurrentArea();
4248 if (!map || !map->HasActor(target)) {
4249 //stay around for the next evaluation
4250 return FX_APPLIED;
4252 Point p(fx->PosX,fx->PosY);
4253 MoveBetweenAreasCore(target, fx->Resource, p, fx->Parameter2, true);
4254 //this effect doesn't stick
4255 return FX_NOT_APPLIED;
4258 // 0xbb Variable:StoreLocalVariable
4259 int fx_local_variable (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4261 //this is a hack, the variable name spreads across the resources
4262 if (0) printf( "fx_local_variable (%2d) %s=%d", fx->Opcode, fx->Resource, fx->Parameter1 );
4263 target->locals->SetAt(fx->Resource, fx->Parameter1);
4264 //local variable effects are not applied, they will be resaved though
4265 return FX_NOT_APPLIED;
4268 // 0xbc AuraCleansingModifier
4269 int fx_auracleansing_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4271 if (0) printf( "fx_auracleansing_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4272 STAT_SET( IE_AURACLEANSING, fx->Parameter2 );
4273 return FX_APPLIED;
4276 // 0xbd CastingSpeedModifier
4277 int fx_castingspeed_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4279 if (0) printf( "fx_castingspeed_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4280 STAT_MOD( IE_MENTALSPEED );
4281 return FX_APPLIED;
4284 // 0xbe PhysicalSpeedModifier
4285 int fx_attackspeed_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4287 if (0) printf( "fx_attackspeed_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4288 STAT_MOD( IE_PHYSICALSPEED );
4289 return FX_APPLIED;
4292 // 0xbf CastingLevelModifier
4293 int fx_castinglevel_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4295 if (0) printf( "fx_castinglevel_modifier (%2d) Value:%d Type:%d", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4296 switch (fx->Parameter2) {
4297 case 0:
4298 STAT_SET( IE_CASTINGLEVELBONUSMAGE, fx->Parameter1 );
4299 break;
4300 case 1:
4301 STAT_SET( IE_CASTINGLEVELBONUSCLERIC, fx->Parameter1 );
4302 break;
4303 default:
4304 return FX_NOT_APPLIED;
4306 return FX_APPLIED;
4309 // 0xc0 FindFamiliar
4310 // param2 = 1 alignment is in param1
4311 // param2 = 2 resource used
4312 #define FAMILIAR_NORMAL 0
4313 #define FAMILIAR_ALIGNMENT 1
4314 #define FAMILIAR_RESOURCE 2
4316 static EffectRef fx_familiar_constitution_loss_ref={"FamiliarBond",NULL,-1};
4317 static EffectRef fx_familiar_marker_ref={"FamiliarMarker",NULL,-1};
4319 int fx_find_familiar (Scriptable* Owner, Actor* target, Effect* fx)
4321 if (0) printf( "fx_find_familiar (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4323 if (!target) {
4324 return FX_NOT_APPLIED;
4327 if (!target->GetCurrentArea()) {
4328 return FX_APPLIED;
4331 if (fx->Parameter2!=FAMILIAR_RESOURCE) {
4332 ieDword alignment;
4334 if (fx->Parameter2==FAMILIAR_ALIGNMENT) {
4335 alignment = fx->Parameter1;
4336 } else {
4337 alignment = target->GetStat(IE_ALIGNMENT);
4338 alignment = ((alignment&AL_LC_MASK)>>4)*3+(alignment&AL_GE_MASK)-4;
4340 if (alignment>8) {
4341 return FX_NOT_APPLIED;
4343 memcpy(fx->Resource, core->GetGame()->Familiars[alignment],sizeof(ieResRef) );
4344 fx->Parameter2=FAMILIAR_RESOURCE;
4347 //summon familiar with fx->Resource
4348 Point p(fx->PosX, fx->PosY);
4349 Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
4350 Actor *fam = core->SummonCreature(fx->Resource, fx->Resource2, Owner, target, p, EAM_DEFAULT, 0, newfx, 0);
4351 delete newfx;
4353 if (fam) {
4354 //Make the familiar an NPC (MoveGlobal needs this)
4355 core->GetGame()->AddNPC(fam);
4357 //Add some essential effects
4358 newfx = EffectQueue::CreateEffect(fx_familiar_constitution_loss_ref, (ieDword) -10, 0, FX_DURATION_INSTANT_PERMANENT);
4359 core->ApplyEffect(newfx, fam, fam);
4360 delete newfx;
4362 newfx = EffectQueue::CreateEffect(fx_familiar_marker_ref, 0, 0, FX_DURATION_INSTANT_PERMANENT);
4363 core->ApplyEffect(newfx, fam, fam);
4364 delete newfx;
4366 return FX_NOT_APPLIED;
4369 // 0xc1 InvisibleDetection
4370 int fx_see_invisible_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4372 if (0) printf( "fx_see_invisible_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4373 STAT_SET( IE_SEEINVISIBLE, fx->Parameter2 );
4374 return FX_APPLIED;
4377 // 0xc2 IgnoreDialogPause
4378 int fx_ignore_dialogpause_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4380 if (0) printf( "fx_ignore_dialogpause_modifier (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4381 STAT_SET( IE_IGNOREDIALOGPAUSE, fx->Parameter2 );
4382 return FX_APPLIED;
4385 //0xc3 FamiliarBond
4386 //when this effect's target dies it should incur damage on protagonist
4387 static EffectRef fx_damage_opcode_ref={"Damage",NULL,-1};
4388 static EffectRef fx_maximum_hp_modifier_ref={"MaximumHPModifier",NULL,-1};
4390 int fx_familiar_constitution_loss (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4392 if (0) printf( "fx_familiar_constitution_loss (%2d): Loss: %d\n", fx->Opcode,(signed) fx->Parameter1 );
4393 if (! (STAT_GET(IE_STATE_ID)&STATE_NOSAVE)) {
4394 return FX_APPLIED;
4396 Effect *newfx;
4397 //familiar died
4398 Actor *master = core->GetGame()->FindPC(1);
4399 if (!master) return FX_NOT_APPLIED;
4400 //maximum hp (param1 is a negative value)
4401 newfx = EffectQueue::CreateEffect(fx_maximum_hp_modifier_ref, fx->Parameter1, 0, FX_DURATION_INSTANT_PERMANENT);
4402 core->ApplyEffect(newfx, master, master);
4403 delete newfx;
4405 //damage
4406 newfx = EffectQueue::CreateEffect(fx_damage_opcode_ref, 0, 0, FX_DURATION_INSTANT_PERMANENT);
4407 core->ApplyEffect(newfx, master, master);
4408 delete newfx;
4410 return FX_NOT_APPLIED;
4413 //0xc4 FamiliarMarker
4414 int fx_familiar_marker (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4416 if (0) printf( "fx_familiar_marker (%2d)\n", fx->Opcode );
4417 if (! (STAT_GET(IE_STATE_ID)&STATE_NOSAVE)) {
4418 //TODO: where to disable familiar?
4419 //core->GetGame()->WeatherBits|=1;
4420 return FX_APPLIED;
4422 //TODO: enable familiar?
4423 //core->GetGame()->WeatherBits&=~1;
4424 return FX_NOT_APPLIED;
4427 // 0xc5 Bounce:Projectile
4428 int fx_bounce_projectile (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4430 if (0) printf( "fx_bounce_projectile (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4431 STAT_BIT_OR( IE_BOUNCE, BNC_PROJECTILE );
4432 return FX_APPLIED;
4435 // 0xc6 Bounce:Opcode
4436 int fx_bounce_opcode (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4438 if (0) printf( "fx_bounce_opcode (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4439 STAT_BIT_OR( IE_BOUNCE, BNC_OPCODE );
4440 target->AddPortraitIcon(PI_BOUNCE2);
4441 return FX_APPLIED;
4444 // 0xc7 Bounce:SpellLevel
4445 int fx_bounce_spelllevel (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4447 if (0) printf( "fx_bounce_spellevel (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4448 STAT_BIT_OR( IE_BOUNCE, BNC_LEVEL );
4449 target->AddPortraitIcon(PI_BOUNCE2);
4450 return FX_APPLIED;
4453 // 0xc8 Bounce:SpellLevelDec
4454 int fx_bounce_spelllevel_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4456 if (0) printf( "fx_bounce_spellevel_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4457 STAT_BIT_OR( IE_BOUNCE, BNC_LEVEL_DEC );
4458 target->AddPortraitIcon(PI_BOUNCE);
4459 return FX_APPLIED;
4462 //0xc9 Protection:SpellLevelDec
4463 int fx_protection_spelllevel_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4465 if (0) printf( "fx_protection_spelllevel_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4466 STAT_BIT_OR( IE_IMMUNITY, IMM_LEVEL_DEC );
4467 target->AddPortraitIcon(PI_BOUNCE2);
4468 return FX_APPLIED;
4471 //0xca Bounce:School
4472 int fx_bounce_school (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4474 if (0) printf( "fx_bounce_school (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4475 STAT_BIT_OR( IE_BOUNCE, BNC_SCHOOL );
4476 target->AddPortraitIcon(PI_BOUNCE2);
4477 return FX_APPLIED;
4480 // 0xcb Bounce:SecondaryType
4481 int fx_bounce_secondary_type (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4483 if (0) printf( "fx_bounce_secondary_type (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4484 STAT_BIT_OR( IE_BOUNCE, BNC_SECTYPE );
4485 target->AddPortraitIcon(PI_BOUNCE2);
4486 return FX_APPLIED;
4489 // 0xcc //resist school
4490 int fx_protection_school (Scriptable* /*Owner*/, Actor* target, Effect *fx)
4492 if (0) printf( "fx_protection_school (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4493 STAT_BIT_OR( IE_IMMUNITY, IMM_SCHOOL);
4494 return FX_APPLIED;
4497 // 0xcd //resist sectype
4498 int fx_protection_secondary_type (Scriptable* /*Owner*/, Actor* target, Effect *fx)
4500 if (0) printf( "fx_protection_secondary_type (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4501 STAT_BIT_OR( IE_IMMUNITY, IMM_SECTYPE);
4502 return FX_APPLIED;
4505 //0xce Protection:Spell
4506 int fx_resist_spell (Scriptable* /*Owner*/, Actor* target, Effect *fx)
4508 if (0) printf( "fx_resist_spell (%2d): Resource: %s\n", fx->Opcode, fx->Resource );
4509 if (strnicmp(fx->Resource,fx->Source,sizeof(fx->Resource)) ) {
4510 STAT_BIT_OR( IE_IMMUNITY, IMM_RESOURCE);
4511 return FX_APPLIED;
4513 //this has effect only on first apply, it will stop applying the spell
4514 return FX_ABORT;
4517 // ??? Protection:SpellDec
4518 int fx_resist_spell_dec (Scriptable* /*Owner*/, Actor* target, Effect *fx)
4520 if (0) printf( "fx_resist_spell_dec (%2d): Resource: %s\n", fx->Opcode, fx->Resource );
4521 if (strnicmp(fx->Resource,fx->Source,sizeof(fx->Resource)) ) {
4522 STAT_BIT_OR( IE_IMMUNITY, IMM_RESOURCE_DEC);
4523 return FX_APPLIED;
4525 //this has effect only on first apply, it will stop applying the spell
4526 return FX_ABORT;
4529 // 0xcf Bounce:Spell
4530 int fx_bounce_spell (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4532 if (0) printf( "fx_bounce_spell (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4533 STAT_BIT_OR( IE_BOUNCE, BNC_RESOURCE );
4534 return FX_APPLIED;
4537 // ??? Bounce:SpellDec
4538 int fx_bounce_spell_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4540 if (0) printf( "fx_bounce_spell (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4541 STAT_BIT_OR( IE_BOUNCE, BNC_RESOURCE_DEC );
4542 return FX_APPLIED;
4545 // 0xd0 MinimumHPModifier
4546 // the original engine didn't allow modifying of this stat
4547 // it allowed only setting it, and only by one instance
4548 int fx_minimum_hp_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4550 if (0) printf( "fx_minimum_hp_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4552 STAT_MOD( IE_MINHITPOINTS );
4553 return FX_APPLIED;
4556 //0xd1 PowerWordKill
4557 int fx_power_word_kill (Scriptable* Owner, Actor* target, Effect* fx)
4559 if (0) printf( "fx_power_word_kill (%2d): HP: %d Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4560 ieDword limit = 60;
4562 if (fx->Parameter1) {
4563 limit = fx->Parameter1;
4565 //normally this would work only with hitpoints
4566 //but why not add some extra features
4567 ieDword stat = target->GetStat (fx->Parameter2&0xffff);
4569 if (stat < limit) {
4570 target->Die( Owner );
4572 return FX_NOT_APPLIED;
4575 //0xd2 PowerWordStun
4576 int fx_power_word_stun (Scriptable* Owner, Actor* target, Effect* fx)
4578 if (0) printf( "fx_power_word_stun (%2d): HP: %d Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4579 ieDword limit = 90;
4581 if (fx->Parameter1) {
4582 limit = fx->Parameter1;
4584 //normally this would work only with hitpoints
4585 //but why not add some extra features
4586 ieDword stat = target->GetStat (fx->Parameter2&0xffff);
4587 ieDword x = fx->Parameter2>>16; //dice sides
4589 if (stat > limit) {
4590 return FX_NOT_APPLIED;
4592 //recalculate delay
4593 stat = (stat * 3 + limit - 1) / limit;
4594 //delay will be calculated as 1dx/2dx/3dx
4595 //depending on the current hitpoints (or the stat in param2)
4596 stat = core->Roll(stat,x?x:4,0) * ROUND_SIZE;
4597 fx->Duration = core->GetGame()->GameTime+stat;
4598 fx->TimingMode = FX_DURATION_ABSOLUTE;
4599 fx->Opcode = EffectQueue::ResolveEffect(fx_set_stun_state_ref);
4600 return fx_set_stun_state(Owner,target,fx);
4603 //0xd3 State:Imprisonment (avatar removal plus portrait icon)
4604 int fx_imprisonment (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4606 if (0) printf( "fx_inprisonment (%2d)\n", fx->Opcode );
4607 target->SetMCFlag(MC_HIDDEN, BM_OR);
4608 target->AddPortraitIcon(PI_PRISON);
4609 return FX_APPLIED;
4612 //0xd4 Cure:Imprisonment
4613 static EffectRef fx_imprisonment_ref={"Imprisonment",NULL,-1};
4614 static EffectRef fx_maze_ref={"Maze",NULL,-1};
4616 int fx_freedom (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4618 if (0) printf( "fx_freedom (%2d)\n", fx->Opcode );
4619 target->fxqueue.RemoveAllEffects( fx_imprisonment_ref );
4620 target->fxqueue.RemoveAllEffects( fx_maze_ref );
4621 return FX_NOT_APPLIED;
4624 //0xd5 Maze
4625 int fx_maze (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4627 if (0) printf( "fx_maze (%2d)\n", fx->Opcode );
4628 target->SetMCFlag(MC_HIDDEN, BM_OR);
4629 target->AddPortraitIcon(PI_MAZE);
4630 return FX_APPLIED;
4633 //0xd6 CastFromList
4634 int fx_select_spell (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
4636 if (0) printf( "fx_select_spell (%2d) %d\n", fx->Opcode, fx->Parameter2 );
4637 //if parameter2==0 -> cast spells from 2da (all spells listed in 2da)
4638 //if parameter2==1 -> cast spells from book (all known spells, no need of memorize)
4639 return FX_NOT_APPLIED;
4642 // 0xd7 PlayVisualEffect
4643 int fx_play_visual_effect (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4645 if (0) printf( "fx_play_visual_effect (%2d): Resource: %s Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
4647 //this is in the original engine (dead actors lose this effect)
4648 if (STATE_GET( STATE_DEAD) ) {
4649 return FX_NOT_APPLIED;
4652 //delay action until area is loaded to avoid crash
4653 Map *map = target->GetCurrentArea();
4654 if (!map) return FX_APPLIED;
4656 //if it is sticky, don't add it if it is already played
4657 if (fx->Parameter2) {
4658 if (!target->HasVVCCell(fx->Resource) ) {
4659 return FX_NOT_APPLIED;
4663 ScriptedAnimation* sca = gamedata->GetScriptedAnimation(fx->Resource, false);
4665 //don't crash on nonexistent resources
4666 if (!sca) {
4667 return FX_NOT_APPLIED;
4670 if (fx->TimingMode!=FX_DURATION_INSTANT_PERMANENT) {
4671 sca->SetDefaultDuration(fx->Duration-core->GetGame()->GameTime);
4673 if (fx->Parameter2) {
4674 //play over target (sticky)
4675 target->AddVVCell( sca );
4676 return FX_APPLIED;
4679 //not sticky
4680 sca->XPos=fx->PosX;
4681 sca->YPos=fx->PosY;
4682 map->AddVVCell( sca );
4683 return FX_NOT_APPLIED;
4686 //d8 LevelDrainModifier
4688 static EffectRef fx_leveldrain_ref={"LevelDrainModifier",NULL,-1};
4690 int fx_leveldrain_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4692 if (0) printf( "fx_leveldrain_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 );
4694 //never subtract more than the maximum hitpoints
4695 ieDword x = STAT_GET(IE_MAXHITPOINTS)-1;
4696 if (fx->Parameter1*4<x) {
4697 x=fx->Parameter1*4;
4699 STAT_ADD(IE_LEVELDRAIN, fx->Parameter1);
4700 STAT_SUB(IE_MAXHITPOINTS, x);
4701 STAT_SUB(IE_SAVEVSDEATH, fx->Parameter1);
4702 STAT_SUB(IE_SAVEVSWANDS, fx->Parameter1);
4703 STAT_SUB(IE_SAVEVSPOLY, fx->Parameter1);
4704 STAT_SUB(IE_SAVEVSBREATH, fx->Parameter1);
4705 STAT_SUB(IE_SAVEVSSPELL, fx->Parameter1);
4706 target->AddPortraitIcon(PI_LEVELDRAIN);
4707 //decrease current hitpoints on first apply
4708 if (fx->FirstApply) {
4709 //current hitpoints don't have base/modified, only current
4710 BASE_SUB(IE_HITPOINTS, x);
4712 return FX_APPLIED;
4715 //d9 PowerWordSleep
4716 static EffectRef fx_sleep_ref={"State:Sleep",NULL,-1};
4718 int fx_power_word_sleep (Scriptable* Owner, Actor* target, Effect* fx)
4720 if (0) printf( "fx_power_word_sleep (%2d): HP: %d Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4721 ieDword limit = 20;
4723 if (fx->Parameter1) {
4724 limit = fx->Parameter1;
4727 ieDword stat = target->GetStat (fx->Parameter2&0xffff);
4728 ieDword x = fx->Parameter2>>16; //rounds
4729 if (!x) x = 5;
4731 if (stat>limit) {
4732 return FX_NOT_APPLIED;
4734 //translate this effect to a normal sleep effect
4735 //recalculate delay
4736 fx->Duration = core->GetGame()->GameTime+x*ROUND_SIZE;
4737 fx->TimingMode = FX_DURATION_ABSOLUTE;
4738 fx->Opcode = EffectQueue::ResolveEffect(fx_sleep_ref);
4739 fx->Parameter2=0;
4740 return fx_set_unconscious_state(Owner,target,fx);
4743 // 0xda StoneSkinModifier
4744 int fx_stoneskin_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4746 if (0) printf( "fx_stoneskin_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 );
4747 if (!fx->Parameter1) {
4748 return FX_NOT_APPLIED;
4751 //dead actors lose this effect
4752 if (STATE_GET( STATE_DEAD) ) {
4753 return FX_NOT_APPLIED;
4756 //this is the bg2 style stoneskin, not normally using spell states
4757 //but this way we can support hybrid games
4758 if (fx->Parameter2) {
4759 target->SetSpellState(SS_IRONSKIN);
4760 //gradient for iron skins?
4761 } else {
4762 target->SetSpellState(SS_STONESKIN);
4763 SetGradient(target, 14);
4765 STAT_SET(IE_STONESKINS, fx->Parameter1);
4766 target->AddPortraitIcon(PI_STONESKIN);
4767 return FX_APPLIED;
4770 //0xdb ac vs creature type (general effect)
4771 //0xdc DispelSchool
4772 int fx_dispel_school (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4774 if (0) printf( "fx_dispel_school (%2d): Level: %d Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4775 target->fxqueue.RemoveLevelEffects(fx->Parameter1, RL_MATCHSCHOOL, fx->Parameter2);
4776 return FX_NOT_APPLIED;
4778 //0xdd DispelSecondaryType
4779 int fx_dispel_secondary_type (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4781 if (0) printf( "fx_dispel_secondary_type (%2d): Level: %d Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4782 target->fxqueue.RemoveLevelEffects(fx->Parameter1, RL_MATCHSECTYPE, fx->Parameter2);
4783 return FX_NOT_APPLIED;
4786 //0xde RandomTeleport
4787 int fx_teleport_field (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4789 if (0) printf( "fx_teleport_field (%2d): Distance: %d\n", fx->Opcode, fx->Parameter1 );
4791 Map *map = target->GetCurrentArea();
4792 if (!map) {
4793 return FX_NOT_APPLIED;
4795 //this should be the target's position, i think
4796 Point p = target->Pos;
4797 p.x+=core->Roll(1,fx->Parameter1*2,-(signed) (fx->Parameter1));
4798 p.y+=core->Roll(1,fx->Parameter1*2,-(signed) (fx->Parameter1));
4799 target->SetPosition( p, true, 0);
4800 return FX_NOT_APPLIED;
4803 //0xdf //Protection:SchoolDec
4804 int fx_protection_school_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4806 if (0) printf( "fx_protection_school_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4807 if (fx->Parameter1) {
4808 STAT_BIT_OR( IE_IMMUNITY, IMM_SCHOOL_DEC );
4809 return FX_APPLIED;
4811 return FX_NOT_APPLIED;
4814 //0xe0 Cure:LevelDrain
4816 int fx_cure_leveldrain (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4818 if (0) printf( "fx_cure_leveldrain (%2d)\n", fx->Opcode );
4819 //all level drain removed at once???
4820 //if not, then find old effect, remove a number
4821 target->fxqueue.RemoveAllEffects( fx_leveldrain_ref );
4822 return FX_NOT_APPLIED;
4825 //0xe1 Reveal:Magic
4826 //gemrb special: speed and color are custom
4827 int fx_reveal_magic (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4829 if (0) printf( "fx_reveal_magic (%2d)\n", fx->Opcode );
4830 if (target->fxqueue.HasAnyDispellableEffect()) {
4831 if (!fx->Parameter1) {
4832 fx->Parameter1=0xff00; //blue
4835 int speed = (fx->Parameter2 >> 16) & 0xFF;
4836 if (!speed) speed=30;
4837 target->SetColorMod(0xff, RGBModifier::ADD, speed,
4838 fx->Parameter1 >> 8, fx->Parameter1 >> 16,
4839 fx->Parameter1 >> 24, 0);
4841 return FX_NOT_APPLIED;
4844 //0xe2 Protection:SecondaryTypeDec
4845 int fx_protection_secondary_type_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4847 if (0) printf( "fx_protection_secondary_type_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4848 if (fx->Parameter1) {
4849 STAT_BIT_OR( IE_IMMUNITY, IMM_SECTYPE_DEC );
4850 return FX_APPLIED;
4852 return FX_NOT_APPLIED;
4855 //0xe3 Bounce:SchoolDecrement
4856 int fx_bounce_school_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4858 if (0) printf( "fx_bounce_school_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4859 STAT_BIT_OR( IE_BOUNCE, BNC_SCHOOL_DEC );
4860 target->AddPortraitIcon(PI_BOUNCE2);
4861 return FX_APPLIED;
4864 //0xe4 Bounce:SecondaryTypeDecrement
4865 int fx_bounce_secondary_type_dec (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4867 if (0) printf( "fx_bounce_secondary_type_dec (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
4868 STAT_BIT_OR( IE_BOUNCE, BNC_SECTYPE_DEC );
4869 target->AddPortraitIcon(PI_BOUNCE2);
4870 return FX_APPLIED;
4873 //0xe5 DispelSchoolOne
4874 int fx_dispel_school_one (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4876 if (0) printf( "fx_dispel_school_one (%2d): Level: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4877 target->fxqueue.RemoveLevelEffects(fx->Parameter1, RL_MATCHSCHOOL|RL_REMOVEFIRST, fx->Parameter2);
4878 return FX_NOT_APPLIED;
4881 //0xe6 DispelSecondaryTypeOne
4882 int fx_dispel_secondary_type_one (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4884 if (0) printf( "fx_dispel_secondary_type_one (%2d): Level: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4885 target->fxqueue.RemoveLevelEffects(fx->Parameter1,RL_MATCHSECTYPE|RL_REMOVEFIRST, fx->Parameter2);
4886 return FX_NOT_APPLIED;
4889 //0xe7 Timestop
4890 int fx_timestop (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4892 if (0) printf( "fx_timestop (%2d)\n", fx->Opcode);
4893 core->GetGame()->TimeStop(target, fx->Duration);
4894 return FX_NOT_APPLIED;
4897 //0xe8 CastSpellOnCondition
4898 int fx_cast_spell_on_condition (Scriptable* Owner, Actor* target, Effect* fx)
4900 if (0) printf( "fx_cast_spell_on_condition (%2d): Target: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4902 if (fx->FirstApply && fx->Parameter3) {
4903 target->spellbook.HaveSpell( fx->Resource, HS_DEPLETE );
4904 target->spellbook.HaveSpell( fx->Resource2, HS_DEPLETE );
4905 target->spellbook.HaveSpell( fx->Resource3, HS_DEPLETE );
4906 target->spellbook.HaveSpell( fx->Resource4, HS_DEPLETE );
4909 //get subject of check
4910 Actor *actor = NULL;
4911 Map *map = target->GetCurrentArea();
4912 switch(fx->Parameter1) {
4913 //self
4914 case 0: actor = target; break;
4915 //last attacker
4916 case 1: actor = map->GetActorByGlobalID(target->LastHitter); break;
4917 //nearest enemy
4918 //fix this!
4919 //case 2: actor = map->GetActorByGlobalID(target->LastSeen); break;
4920 case 2: actor = GetNearestEnemyOf(map, target, 0); break;
4921 //nearest creature
4922 case 3: actor = map->GetActorByGlobalID(target->LastSeen); break;
4924 if (!actor) {
4925 return FX_APPLIED;
4927 int condition;
4928 //check condition
4929 switch(fx->Parameter2) {
4930 case COND_GOTHIT: //on hit
4931 condition = target->LastDamage;
4932 break;
4933 case COND_NEAR: //
4934 condition = PersonalDistance(actor, target)<30;
4935 break;
4936 case COND_HP_HALF:
4937 condition = actor->GetBase(IE_HITPOINTS)<actor->GetStat(IE_MAXHITPOINTS)/2;
4938 break;
4939 case COND_HP_QUART:
4940 condition = actor->GetBase(IE_HITPOINTS)<actor->GetStat(IE_MAXHITPOINTS)/4;
4941 break;
4942 case COND_HP_LOW:
4943 condition = actor->GetBase(IE_HITPOINTS)<actor->GetStat(IE_MAXHITPOINTS)/10;
4944 break;
4945 case COND_HELPLESS:
4946 condition = actor->GetStat(IE_STATE_ID) & STATE_CANTMOVE;
4947 break;
4948 case COND_POISONED:
4949 condition = actor->GetStat(IE_STATE_ID) & STATE_POISONED;
4950 break;
4951 case COND_ATTACKED:
4952 condition = actor->LastHitter;
4953 break;
4954 case COND_HIT:
4955 condition = actor->LastDamage;
4956 break;
4957 case COND_ALWAYS:
4958 condition = 1;
4959 break;
4960 default:
4961 condition = 0;
4964 if (condition) {
4965 core->ApplySpell(fx->Resource, actor, Owner, fx->Power);
4966 core->ApplySpell(fx->Resource2, actor, Owner, fx->Power);
4967 core->ApplySpell(fx->Resource3, actor, Owner, fx->Power);
4968 core->ApplySpell(fx->Resource4, actor, Owner, fx->Power);
4969 if (fx->Parameter3) {
4970 return FX_NOT_APPLIED;
4973 return FX_APPLIED;
4976 // 0xe9 Proficiency
4977 int fx_proficiency (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4979 if (0) printf( "fx_proficiency (%2d): Value: %d, Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4981 if (fx->Parameter2>=MAX_STATS) return FX_NOT_APPLIED;
4983 //this opcode works only if the previous value was smaller
4984 if (STAT_GET(fx->Parameter2)<fx->Parameter1) {
4985 STAT_SET (fx->Parameter2, fx->Parameter1);
4987 return FX_APPLIED;
4990 // 0xea CreateContingency
4991 static EffectRef fx_contingency_ref={"CastSpellOnCondition",NULL,-1};
4993 int fx_create_contingency (Scriptable* /*Owner*/, Actor* target, Effect* fx)
4995 if (0) printf( "fx_create_contingency (%2d): Level: %d, Count: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
4997 printf("Check source:%s\n", fx->Source);
4998 if (target->fxqueue.HasEffectWithSource(fx_contingency_ref, fx->Source)) {
4999 displaymsg->DisplayConstantStringName(STR_CONTDUP, 0xf0f0f0, target);
5000 return FX_NOT_APPLIED;
5003 if (target->InParty) {
5004 Variables *dict = core->GetDictionary();
5006 dict->SetAt( "P0", target->InParty );
5007 dict->SetAt( "P1", fx->Parameter1 );
5008 dict->SetAt( "P2", fx->Parameter2 );
5009 core->SetEventFlag(EF_SEQUENCER);
5011 return FX_NOT_APPLIED;
5014 #define WB_AWAY 0
5015 #define WB_TOWARDS 1
5016 #define WB_FIXDIR 2
5017 #define WB_OWNDIR 3
5018 #define WB_AWAYOWNDIR 4
5020 // 0xeb WingBuffet
5021 int fx_wing_buffet (Scriptable* Owner, Actor* target, Effect* fx)
5023 if (0) printf( "fx_wing_buffet (%2d): Value: %d, Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5024 //create movement in actor
5026 ieDword dir;
5027 switch(fx->Parameter2) {
5028 case WB_AWAY:
5029 default:
5030 dir = GetOrient(Owner->Pos, target->Pos);
5031 break;
5032 case WB_TOWARDS:
5033 dir = GetOrient(target->Pos, Owner->Pos);
5034 break;
5035 case WB_FIXDIR:
5036 dir = fx->Parameter3;
5037 break;
5038 case WB_OWNDIR:
5039 dir = target->GetOrientation();
5040 break;
5041 case WB_AWAYOWNDIR:
5042 dir = target->GetOrientation()^8;
5043 break;
5045 //could be GL_REBOUND too :)
5046 //add effect to alter target's stance
5047 target->MoveLine( fx->Parameter1, GL_NORMAL, dir );
5048 return FX_NOT_APPLIED;
5051 // 0xec ProjectImage
5053 static EffectRef fx_puppetmarker_ref={"PuppetMarker",NULL,-1};
5055 int fx_puppet_master (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5057 const char * resref = NULL;
5059 if (0) printf( "fx_puppet_master (%2d): Value: %d, Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5060 STAT_SET (IE_PUPPETMASTERTYPE, fx->Parameter1);
5062 //copyself doesn't copy scripts, so the script clearing code is not needed
5063 Actor *copy = target->CopySelf();
5065 Effect *newfx = EffectQueue::CreateUnsummonEffect(fx);
5066 if (newfx) {
5067 core->ApplyEffect(newfx, copy, copy);
5068 delete newfx;
5071 ieResRef script;
5073 //intentionally 7, to leave room for the last letter
5074 strnlwrcpy(script,target->GetScript(SCR_CLASS),7);
5075 //no need of buffer defense as long as you don't mess with the 7 above
5076 strcat(script,"m");
5077 //if the caster is inparty, the script is turned off by the AI disable flag
5078 copy->SetScript(script, SCR_CLASS, target->InParty!=0);
5080 switch(fx->Parameter2)
5082 case 1:
5083 resref = "mislead";
5084 break;
5085 case 2:
5086 resref = "projimg";
5087 break;
5088 case 3:
5089 resref = "simulacr";
5090 break;
5091 default:
5092 resref = fx->Resource;
5093 break;
5095 if (resref[0]) {
5096 core->ApplySpell(resref,copy,copy,0);
5099 //FIXME: parameter1 is unsure, but something similar to what the original engine has there
5100 newfx = EffectQueue::CreateEffectCopy(fx, fx_puppetmarker_ref, target->InParty-1, fx->Parameter2);
5101 if (newfx) {
5102 core->ApplyEffect(newfx, copy, copy);
5103 delete newfx;
5105 return FX_NOT_APPLIED;
5108 // 0xed PuppetMarker
5109 int fx_puppet_marker (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5111 if (0) printf( "fx_puppet_marker (%2d): Value: %d, Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5112 //actually the Type is in parameter2 and the ID is in parameter1
5113 //but for some reason the defines are in the opposite order
5114 STAT_SET (IE_PUPPETTYPE, fx->Parameter1); //cb4 - the ID of the controller
5115 STAT_SET (IE_PUPPETID, fx->Parameter2); //cb8 - the control type
5116 return FX_APPLIED;
5119 // 0xee Disintegrate
5120 int fx_disintegrate (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5122 if (0) printf( "fx_disintegrate (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5123 if (EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
5124 //convert it to a death opcode or apply the new effect?
5125 fx->Opcode = EffectQueue::ResolveEffect(fx_death_ref);
5126 fx->TimingMode = FX_DURATION_INSTANT_PERMANENT;
5127 fx->Parameter1 = 0;
5128 fx->Parameter2 = 0x200;
5129 return FX_APPLIED;
5131 return FX_NOT_APPLIED;
5134 // 0xef Farsee
5135 // 1 view not explored sections too
5136 // 2 param1=range (otherwise visualrange)
5137 // 4 point already set (otherwise use gui)
5138 // 8 use line of sight
5139 #define FS_UNEXPLORED 1
5140 #define FS_VISUALRANGE 2
5141 #define FS_HASPOINT 4
5142 #define FS_LOS 8
5144 int fx_farsee (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5146 if (0) printf( "fx_farsee (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5147 Map *map = target->GetCurrentArea();
5148 if (!map) {
5149 return FX_APPLIED;
5152 if (!(fx->Parameter2&FS_VISUALRANGE)) {
5153 fx->Parameter1=STAT_GET(IE_VISUALRANGE);
5154 fx->Parameter2|=FS_VISUALRANGE;
5157 if (target->InParty) {
5158 //don't start graphical interface if actor isn't in party
5159 if (!(fx->Parameter2&FS_HASPOINT)) {
5160 //start graphical interface
5161 //it will do all the rest of the opcode
5162 //using RevealMap guiscript action
5163 core->EventFlag|=EF_SHOWMAP;
5164 return FX_NOT_APPLIED;
5168 Point p(fx->PosX, fx->PosY);
5170 //don't explore unexplored points
5171 if (!(fx->Parameter2&FS_UNEXPLORED)) {
5172 if (!map->IsVisible(p, 1)) {
5173 return FX_NOT_APPLIED;
5176 map->ExploreMapChunk(p, fx->Parameter1, fx->Parameter2&FS_LOS);
5177 return FX_NOT_APPLIED;
5180 // 0xf0 Icon:Remove
5181 int fx_remove_portrait_icon (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5183 if (0) printf( "fx_remove_portrait_icon (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
5184 target->fxqueue.RemoveAllEffectsWithParam( fx_display_portrait_icon_ref, fx->Parameter2 );
5185 return FX_NOT_APPLIED;
5187 // 0xf1 control creature (same as charm)
5189 // 0xF2 Cure:Confusion
5190 static EffectRef fx_confused_state_ref={"State:Confused",NULL,-1};
5192 int fx_cure_confused_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5194 if (0) printf( "fx_cure_confused_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5195 BASE_STATE_CURE( STATE_CONFUSED );
5196 target->fxqueue.RemoveAllEffects(fx_confused_state_ref);
5197 return FX_NOT_APPLIED;
5200 // 0xf3 DrainItems (this is disabled in ToB)
5201 int fx_drain_items (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5203 if (0) printf( "fx_drain_items (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5204 ieDword i=fx->Parameter1;
5205 while (i--) {
5206 //deplete magic item = 0
5207 //deplete weapon = 1
5208 target->inventory.DepleteItem(fx->Parameter2);
5210 return FX_NOT_APPLIED;
5212 // 0xf4 DrainSpells
5213 int fx_drain_spells (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5215 if (0) printf( "fx_drain_spells (%2d): Count: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5216 ieDword i=fx->Parameter1;
5217 if (fx->Parameter2) {
5218 while(i--) {
5219 if (!target->spellbook.DepleteSpell(IE_SPELL_TYPE_PRIEST)) {
5220 break;
5223 return FX_NOT_APPLIED;
5225 while(i--) {
5226 if (!target->spellbook.DepleteSpell(IE_SPELL_TYPE_WIZARD)) {
5227 break;
5230 return FX_NOT_APPLIED;
5232 // 0xf5 CheckForBerserk
5233 int fx_checkforberserk_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5235 if (0) printf( "fx_checkforberserk_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5236 STAT_SET( IE_CHECKFORBERSERK, fx->Parameter2 );
5237 return FX_APPLIED;
5239 // 0xf6 BerserkStage1Modifier
5240 int fx_berserkstage1_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5242 if (0) printf( "fx_berserkstage1_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5243 STAT_SET( IE_BERSERKSTAGE1, fx->Parameter2 );
5244 return FX_APPLIED;
5246 // 0xf7 BerserkStage2Modifier
5247 int fx_berserkstage2_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5249 if (0) printf( "fx_berserkstage2_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5250 STAT_SET( IE_BERSERKSTAGE2, fx->Parameter2 );
5251 STATE_SET (STATE_BERSERK);
5252 return FX_APPLIED;
5254 // 0xf8 set melee effect generic effect?
5255 // 0xf9 set missile effect generic effect?
5256 // 0xfa DamageLuckModifier
5257 int fx_damageluck_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5259 if (0) printf( "fx_damageluck_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5260 STAT_MOD( IE_DAMAGELUCK );
5261 return FX_APPLIED;
5264 // 0xfb bardsong (generic effect)
5266 // 0xfc SetTrap
5267 int fx_set_area_effect (Scriptable* Owner, Actor* target, Effect* fx)
5269 if (0) printf( "fx_set_trap (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5270 ieDword skill, roll;
5271 Map *map;
5273 map = target->GetCurrentArea();
5274 if (!map) return FX_NOT_APPLIED;
5276 proIterator iter;
5278 //check if trap count is over an amount (only saved traps count)
5279 //actually, only projectiles in trigger phase should count here
5280 if (map->GetTrapCount(iter)>6) {
5281 displaymsg->DisplayConstantStringName(STR_NOMORETRAP, 0xf0f0f0, target);
5282 return FX_NOT_APPLIED;
5285 //check if we are under attack
5286 if (GetNearestEnemyOf(map, target, ORIGIN_SEES_ENEMY|ENEMY_SEES_ORIGIN)) {
5287 displaymsg->DisplayConstantStringName(STR_MAYNOTSETTRAP, 0xf0f0f0, target);
5288 return FX_NOT_APPLIED;
5291 if (Owner->Type==ST_ACTOR) {
5292 skill = ((Actor *)Owner)->GetStat(IE_SETTRAPS);
5293 roll = core->Roll(1,100,0);
5294 } else {
5295 roll=0;
5296 skill=0;
5299 if (roll>skill) {
5300 //failure
5301 displaymsg->DisplayConstantStringName(STR_SNAREFAILED, 0xf0f0f0, target);
5302 //TODO check luck and do some damage effect on target
5303 return FX_NOT_APPLIED;
5305 //success
5306 displaymsg->DisplayConstantStringName(STR_SNARESUCCEED, 0xf0f0f0, target);
5307 Owner->CastSpellPoint(fx->Resource, target->Pos, false);
5308 return FX_NOT_APPLIED;
5311 // 0xfd SetMapNote
5312 int fx_set_map_note (Scriptable* Owner, Actor* target, Effect* fx)
5314 if (0) printf( "fx_set_map_note (%2d): StrRef: %d Color: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5315 Scriptable *marker = target?target:Owner;
5316 Map *map = marker->GetCurrentArea();
5317 if (!map) return FX_APPLIED; //delay effect
5318 Point p(fx->PosX, fx->PosY);
5319 char *text = core->GetString(fx->Parameter1, 0);
5320 map->AddMapNote(p, fx->Parameter2, text, fx->Parameter1);
5321 return FX_NOT_APPLIED;
5324 // 0xfe RemoveMapNote
5325 int fx_remove_map_note (Scriptable* Owner, Actor* target, Effect* fx)
5327 if (0) printf( "fx_remove_map_note (%2d)\n", fx->Opcode);
5328 Scriptable *marker = target?target:Owner;
5329 Map *map = marker->GetCurrentArea();
5330 if (!map) return FX_APPLIED; //delay effect
5331 Point p(fx->PosX, fx->PosY);
5332 map->RemoveMapNote(p);
5333 return FX_NOT_APPLIED;
5336 // 0xff Item:CreateDays
5337 int fx_create_item_days (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5339 if (0) printf( "fx_create_item_days (%2d)\n", fx->Opcode );
5340 target->inventory.AddSlotItemRes( fx->Resource, SLOT_ONLYINVENTORY, fx->Parameter1, fx->Parameter3, fx->Parameter4 );
5341 if ((fx->TimingMode&0xff) == FX_DURATION_INSTANT_LIMITED) {
5342 //if this effect has expiration, then it will remain as a remove_item
5343 //on the effect queue, inheriting all the parameters
5344 //duration needs a hack (recalculate it for days)
5345 //no idea if this multiplier is ok
5346 fx->Duration+=(fx->Duration-core->GetGame()->GameTime)*2400;
5347 fx->Opcode=EffectQueue::ResolveEffect(fx_remove_inventory_item_ref);
5348 fx->TimingMode=FX_DURATION_DELAY_PERMANENT;
5349 return FX_APPLIED;
5351 return FX_NOT_APPLIED;
5354 // 0x100 Sequencer:Store
5355 int fx_store_spell_sequencer(Scriptable* /*Owner*/, Actor* target, Effect* fx)
5357 if (0) printf( "fx_store_spell_sequencer (%2d)\n", fx->Opcode );
5358 //just display the spell sequencer portrait icon
5359 target->AddPortraitIcon(PI_SEQUENCER);
5360 if (fx->FirstApply && fx->Parameter3) {
5361 target->spellbook.HaveSpell( fx->Resource, HS_DEPLETE );
5362 target->spellbook.HaveSpell( fx->Resource2, HS_DEPLETE );
5363 target->spellbook.HaveSpell( fx->Resource3, HS_DEPLETE );
5364 target->spellbook.HaveSpell( fx->Resource4, HS_DEPLETE );
5366 return FX_APPLIED;
5369 // 0x101 Sequencer:Create
5370 static EffectRef fx_spell_sequencer_active_ref={"Sequencer:Store",NULL,-1};
5372 int fx_create_spell_sequencer(Scriptable* /*Owner*/, Actor* target, Effect* fx)
5374 if (0) printf( "fx_create_spell_sequencer (%2d): Level: %d, Count: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5375 printf("Check source:%s\n", fx->Source);
5376 if (target->fxqueue.HasEffectWithSource(fx_spell_sequencer_active_ref, fx->Source)) {
5377 displaymsg->DisplayConstantStringName(STR_SEQDUP, 0xf0f0f0, target);
5378 return FX_NOT_APPLIED;
5380 //just a call to activate the spell sequencer creation gui
5381 if (target->InParty) {
5382 Variables *dict = core->GetDictionary();
5384 dict->SetAt( "P0", target->InParty );
5385 dict->SetAt( "P1", fx->Parameter1 ); //maximum level
5386 dict->SetAt( "P2", fx->Parameter2 | (2<<16) ); //count and target type
5387 core->SetEventFlag(EF_SEQUENCER);
5389 return FX_NOT_APPLIED;
5392 // 0x102 Sequencer:Activate
5394 int fx_activate_spell_sequencer(Scriptable* Owner, Actor* target, Effect* fx)
5396 if (0) printf( "fx_activate_spell_sequencer (%2d): Resource: %s\n", fx->Opcode, fx->Resource );
5397 if (Owner->Type!=ST_ACTOR) {
5398 return FX_NOT_APPLIED;
5401 Effect *sequencer = ((Actor *) Owner)->fxqueue.HasEffect(fx_spell_sequencer_active_ref);
5402 if (sequencer) {
5403 //cast 1-4 spells stored in the spell sequencer
5404 core->ApplySpell(sequencer->Resource, target, Owner, fx->Power);
5405 core->ApplySpell(sequencer->Resource2, target, Owner, fx->Power);
5406 core->ApplySpell(sequencer->Resource3, target, Owner, fx->Power);
5407 core->ApplySpell(sequencer->Resource4, target, Owner, fx->Power);
5408 //remove the spell sequencer store effect
5409 sequencer->TimingMode=FX_DURATION_JUST_EXPIRED;
5411 return FX_NOT_APPLIED;
5414 // 0x103 SpellTrap (Protection:SpellLevelDec + recall spells)
5415 int fx_spelltrap(Scriptable* /*Owner*/, Actor* target, Effect* fx)
5417 if (0) printf( "fx_spelltrap (%2d): Count: %d, Level: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5418 if (fx->Parameter3) {
5419 target->RestoreSpellLevel(fx->Parameter3, 0);
5420 fx->Parameter3=0;
5422 if (fx->Parameter1<=0) {
5423 //gone down to zero
5424 return FX_NOT_APPLIED;
5426 target->SetOverlay(OV_SPELLTRAP);
5427 target->AddPortraitIcon(PI_SPELLTRAP);
5428 return FX_APPLIED;
5431 //0x104 Crash104
5432 //0x138 Crash138
5433 int fx_crash (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
5435 if (0) printf( "fx_crash (%2d): Param1: %d, Param2: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5436 return FX_NOT_APPLIED;
5439 // 0x105 RestoreSpells
5440 int fx_restore_spell_level(Scriptable* /*Owner*/, Actor* target, Effect* fx)
5442 if (0) printf( "fx_restore_spell_level (%2d): Level: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5443 target->RestoreSpellLevel(fx->Parameter1, fx->Parameter2);
5444 return FX_NOT_APPLIED;
5446 // 0x106 VisualRangeModifier
5447 int fx_visual_range_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5449 if (0) printf( "fx_visual_range_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5450 STAT_MOD( IE_VISUALRANGE );
5451 return FX_APPLIED;
5454 // 0x107 BackstabModifier
5455 int fx_backstab_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5457 if (0) printf( "fx_visual_range_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5458 //this is how it is done in the original engine, i don't know why they would do this
5459 //ctrl-r would probably remove it otherwise
5460 //Why they didn't fix it in the spell/item is beyond me
5461 if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT)
5462 fx->TimingMode=FX_DURATION_INSTANT_PERMANENT_AFTER_BONUSES;
5463 STAT_MOD( IE_BACKSTABDAMAGEMULTIPLIER );
5464 return FX_APPLIED;
5467 // 0x108 DropWeapon
5468 int fx_drop_weapon (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5470 if (fx->Resource[0]) {
5471 target->DropItem(fx->Resource, 0);
5472 return FX_NOT_APPLIED;
5474 switch (fx->Parameter2) {
5475 case 0:
5476 target->DropItem(-1, 0);
5477 break;
5478 case 1:
5479 target->DropItem(target->inventory.GetEquippedSlot(), 0);
5480 break;
5481 default:
5482 target->DropItem(fx->Parameter1, 0);
5483 break;
5485 return FX_NOT_APPLIED;
5487 // 0x109 ModifyGlobalVariable
5488 int fx_modify_global_variable (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
5490 Game *game = core->GetGame();
5491 //convert it to internal variable format
5492 if (!fx->IsVariable) {
5493 char *poi=fx->Resource+8;
5494 memmove(poi, fx->Resource2,8);
5495 poi+=8;
5496 memmove(poi, fx->Resource3,8);
5497 poi+=8;
5498 memmove(poi, fx->Resource4,8);
5499 fx->IsVariable=1;
5502 //hack for IWD
5503 if (!fx->Resource[0]) {
5504 strnuprcpy(fx->Resource,"RETURN_TO_LONELYWOOD",32);
5507 if (0) printf( "fx_modify_global_variable (%2d): Variable: %s Value: %d Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter1, fx->Parameter2 );
5508 if (fx->Parameter2) {
5509 ieDword var = 0;
5510 //use resource memory area as variable name
5511 game->locals->Lookup(fx->Resource, var);
5512 game->locals->SetAt(fx->Resource, var+fx->Parameter1);
5513 } else {
5514 game->locals->SetAt(fx->Resource, fx->Parameter1);
5516 return FX_NOT_APPLIED;
5518 // 0x10a RemoveImmunity
5519 EffectRef immunity_effect_ref={"Protection:Spell",NULL,-1};
5521 int fx_remove_immunity(Scriptable* /*Owner*/, Actor* target, Effect* fx)
5523 if (0) printf( "fx_remove_immunity (%2d): %s\n", fx->Opcode, fx->Resource );
5524 target->fxqueue.RemoveAllEffectsWithResource(immunity_effect_ref, fx->Resource);
5525 return FX_NOT_APPLIED;
5528 // 0x10b protection from display string is a generic effect
5529 // 0x10c ExploreModifier
5530 int fx_explore_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5532 if (0) printf( "fx_explore_modifier (%2d)\n", fx->Opcode );
5533 if (fx->Parameter2) {
5534 //gemrb modifier
5535 STAT_SET (IE_EXPLORE, fx->Parameter1);
5536 } else {
5537 STAT_SET (IE_EXPLORE, 1);
5539 return FX_APPLIED;
5541 // 0x10d ScreenShake
5542 int fx_screenshake (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
5544 if (0) printf( "fx_screenshake (%2d): Strength: %d\n", fx->Opcode, fx->Parameter1 );
5545 core->timer->SetScreenShake( fx->Parameter1, fx->Parameter1, 1);
5546 return FX_APPLIED;
5549 // 0x10e Cure:CasterHold
5550 static EffectRef fx_pause_caster_modifier_ref={"PauseTarget",NULL,-1};
5552 int fx_unpause_caster (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5554 if (0) printf( "fx_unpause_caster (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5555 Effect *eff = target->fxqueue.HasEffect(fx_pause_caster_modifier_ref);
5556 if (eff) {
5557 eff->Parameter1-=fx->Parameter2;
5559 return FX_NOT_APPLIED;
5561 // 0x10f AvatarRemoval
5562 // 0x104 AvatarRemoval (iwd)
5563 int fx_avatar_removal (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5565 if (0) printf( "fx_avatar_removal (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5566 //FIXME: this is a permanent irreversible effect in IWD
5567 //if it is different in bg2, then create another effect
5568 //bg2 calls this SummonDisable
5569 BASE_SET(IE_AVATARREMOVAL, 1);
5570 return FX_NOT_APPLIED;
5572 // 0x110 ApplyEffectRepeat
5573 int fx_apply_effect_repeat (Scriptable* Owner, Actor* target, Effect* fx)
5575 ieDword i; //moved here because msvc6 cannot handle it otherwise
5577 if (0) printf( "fx_apply_effect_repeat (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5579 Point p(fx->PosX, fx->PosY);
5580 Effect *newfx = core->GetEffect(fx->Resource, fx->Power, p);
5581 //core->GetEffect is a borrowed reference, don't delete it
5582 if (!newfx) {
5583 return FX_NOT_APPLIED;
5586 switch (fx->Parameter2) {
5587 case 0: //once per second
5588 case 1: //crash???
5589 core->ApplyEffect(newfx, target, Owner);
5590 break;
5591 case 2://param1 times every second
5592 for (i=0;i<fx->Parameter1;i++) {
5593 core->ApplyEffect(newfx, target, Owner);
5595 break;
5596 case 3: //once every Param1 second
5597 if (fx->Parameter1 && (core->GetGame()->GameTime%fx->Parameter1)) {
5598 core->ApplyEffect(newfx, target, Owner);
5600 break;
5601 case 4: //param3 times every Param1 second
5602 if (fx->Parameter1 && (core->GetGame()->GameTime%fx->Parameter1)) {
5603 for (i=0;i<fx->Parameter3;i++) {
5604 core->ApplyEffect(newfx, target, Owner);
5607 break;
5609 return FX_APPLIED;
5612 // 0x111 RemoveProjectile
5613 int fx_remove_projectile (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5615 ieDword *projectilelist;
5617 //instant effect
5618 if (0) printf( "fx_remove_projectile (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5620 if (!target) return FX_NOT_APPLIED;
5621 Map *area = target->GetCurrentArea();
5622 if (!area) return FX_NOT_APPLIED;
5624 switch (fx->Parameter2) {
5625 case 0: //standard bg2
5626 projectilelist = core->GetListFrom2DA("clearair");
5627 break;
5628 case 1: //you can give a 2da for projectile list (gemrb)
5629 projectilelist = core->GetListFrom2DA(fx->Resource);
5630 break;
5631 case 2: //or you can give one single projectile in param1 (gemrb)
5632 projectilelist = (ieDword *) malloc(2*sizeof(ieDword));
5633 projectilelist[0]=1;
5634 projectilelist[1]=fx->Parameter1;
5635 break;
5636 default:
5637 return FX_NOT_APPLIED;
5639 //The first element is the counter, so don't decrease the counter here
5640 Point p(fx->PosX, fx->PosY);
5642 while(projectilelist[0]) {
5643 ieDword projectile = projectilelist[projectilelist[0]];
5644 proIterator piter;
5646 size_t cnt = area->GetProjectileCount(piter);
5647 while( cnt--) {
5648 Projectile *pro = *piter;
5649 if ((pro->GetType()==projectile) && pro->PointInRadius(p) ) {
5650 pro->Cleanup();
5653 if (target) {
5654 target->fxqueue.RemoveAllEffectsWithProjectile(projectile);
5656 projectilelist[0]--;
5658 free(projectilelist);
5659 return FX_NOT_APPLIED;
5662 // 0x112 TeleportToTarget
5663 int fx_teleport_to_target (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5665 if (0) printf( "fx_teleport_to_target (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5666 Map *map = target->GetCurrentArea();
5667 if (map) {
5668 Actor *victim = map->GetActorByGlobalID(target->LastAttacker);
5669 if (victim) {
5670 target->SetPosition( victim->Pos, true, 0 );
5673 return FX_NOT_APPLIED;
5675 // 0x113 HideInShadowsModifier
5676 int fx_hide_in_shadows_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5678 if (0) printf( "fx_hide_in_shadows_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5679 STAT_MOD( IE_HIDEINSHADOWS );
5680 return FX_APPLIED;
5682 // 0x114 DetectIllusionsModifier
5683 int fx_detect_illusion_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5685 if (0) printf( "fx_detect_illusion_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5686 STAT_MOD( IE_DETECTILLUSIONS );
5687 return FX_APPLIED;
5689 // 0x115 SetTrapsModifier
5690 int fx_set_traps_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5692 if (0) printf( "fx_set_traps_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5693 STAT_MOD( IE_SETTRAPS );
5694 return FX_APPLIED;
5696 // 0x116 ToHitBonusModifier
5697 int fx_to_hit_bonus_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5699 if (0) printf( "fx_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5700 HandleBonus( target, IE_HITBONUS, fx->Parameter1, fx->TimingMode );
5701 return FX_APPLIED;
5704 // 0x117 RenableButton
5705 static EffectRef fx_disable_button_ref={"DisableButton",NULL,-1};
5707 int fx_renable_button (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5709 //removes the disable button effect
5710 if (0) printf( "fx_renable_button (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
5711 target->fxqueue.RemoveAllEffectsWithParam( fx_disable_button_ref, fx->Parameter2 );
5712 return FX_NOT_APPLIED;
5714 // 0x118 ForceSurgeModifier
5715 int fx_force_surge_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5717 if (0) printf( "fx_force_surge_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5718 STAT_MOD( IE_FORCESURGE );
5719 return FX_APPLIED;
5722 // 0x119 WildSurgeModifier
5723 int fx_wild_surge_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5725 if (0) printf( "fx_wild_surge_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5726 STAT_MOD( IE_SURGEMOD );
5727 return FX_APPLIED;
5730 // 0x11a ScriptingState
5731 int fx_scripting_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5733 if (0) printf( "fx_scripting_state (%2d): Value: %d, Stat: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5735 //original engine didn't check boundaries, causing crashes
5736 //we allow only positive indices (some extra stats are still addressable)
5737 if (fx->Parameter2>100) {
5738 return FX_NOT_APPLIED;
5740 //original engine used only single byte value, we allow full dword
5741 STAT_SET( IE_SCRIPTINGSTATE1+fx->Parameter2, fx->Parameter1 );
5742 return FX_APPLIED;
5745 // 0x11b ApplyEffectCurse
5746 int fx_apply_effect_curse (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5748 if (0) printf( "fx_apply_effect_curse (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5750 //this effect executes a file effect in place of this effect
5751 //the file effect inherits the target and the timingmode, but gets
5752 //a new chance to roll percents
5753 int ret = FX_NOT_APPLIED;
5754 if (!target) {
5755 return ret;
5758 if (EffectQueue::match_ids( target, fx->Parameter2, fx->Parameter1) ) {
5759 Point p(fx->PosX, fx->PosY);
5761 //apply effect, if the effect is a goner, then kill
5762 //this effect too
5763 Effect *newfx = core->GetEffect(fx->Resource, fx->Power, p);
5764 if (newfx) {
5765 Effect *myfx = new Effect;
5766 memcpy(myfx, newfx, sizeof(Effect));
5767 myfx->random_value = core->Roll(1,100,0);
5768 myfx->TimingMode=fx->TimingMode;
5769 myfx->Duration=fx->Duration;
5770 myfx->Target = FX_TARGET_PRESET;
5771 ret = target->fxqueue.ApplyEffect(target, myfx, fx->FirstApply);
5772 delete myfx;
5774 //newfx is a borrowed reference don't delete it
5776 return ret;
5779 // 0x11c MeleeHitModifier
5780 int fx_melee_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5782 if (0) printf( "fx_melee_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5783 STAT_MOD( IE_MELEETOHIT );
5784 return FX_APPLIED;
5787 // 0x11d MeleeDamageModifier
5788 int fx_melee_damage_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5790 if (0) printf( "fx_melee_damage_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5791 STAT_MOD( IE_MELEEDAMAGE );
5792 return FX_APPLIED;
5795 // 0x11e MissileDamageModifier
5796 int fx_missile_damage_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5798 if (0) printf( "fx_missile_damage_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5799 STAT_MOD( IE_MISSILEDAMAGE );
5800 return FX_APPLIED;
5803 // 0x11f NoCircleState
5804 int fx_no_circle_state (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5806 if (0) printf( "fx_missile_damage_modifier (%2d)\n", fx->Opcode);
5807 STAT_SET( IE_NOCIRCLE, 1 );
5808 return FX_APPLIED;
5811 // 0x120 FistHitModifier
5812 int fx_fist_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5814 if (0) printf( "fx_fist_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5815 STAT_MOD( IE_FISTHIT );
5816 return FX_APPLIED;
5819 // 0x121 FistDamageModifier
5820 int fx_fist_damage_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5822 if (0) printf( "fx_fist_damage_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5823 STAT_MOD( IE_FISTDAMAGE );
5824 return FX_APPLIED;
5826 //0x122 TitleModifier
5827 int fx_title_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5829 if (0) printf( "fx_fist_damage_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5830 if (fx->Parameter2) {
5831 STAT_SET( IE_TITLE2, fx->Parameter1 );
5832 } else {
5833 STAT_SET( IE_TITLE1, fx->Parameter1 );
5835 return FX_APPLIED;
5837 //0x123 DisableOverlay
5838 //FIXME: which overlay is disabled?
5839 //if one of the overlays marked by sanctuary, then
5840 //make the bit correspond to it
5841 int fx_disable_overlay_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5843 if (0) printf( "fx_disable_overlay_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5844 STAT_SET( IE_DISABLEOVERLAY, fx->Parameter1 );
5845 return FX_APPLIED;
5847 //0x124 Protection:Backstab (bg2)
5848 //0x11f Protection:Backstab (how, iwd2)
5849 //3 different games, 3 different methods of flagging this
5850 int fx_no_backstab_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5852 if (0) printf( "fx_no_backstab_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5853 //bg2
5854 STAT_SET( IE_DISABLEBACKSTAB, fx->Parameter1 );
5855 //how
5856 EXTSTATE_SET(EXTSTATE_NO_BACKSTAB);
5857 //iwd2
5858 target->SetSpellState(SS_NOBACKSTAB);
5859 return FX_APPLIED;
5861 //0x125 OffscreenAIModifier
5862 int fx_offscreenai_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5864 if (0) printf( "fx_offscreenai_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5865 STAT_SET( IE_ENABLEOFFSCREENAI, fx->Parameter1 );
5866 target->Activate();
5867 return FX_APPLIED;
5869 //0x126 ExistanceDelayModifier
5870 int fx_existance_delay_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5872 if (0) printf( "fx_existance_delay_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5873 STAT_SET( IE_EXISTANCEDELAY, fx->Parameter1 );
5874 return FX_APPLIED;
5876 //0x127 DisableChunk
5877 int fx_disable_chunk_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5879 if (0) printf( "fx_disable_chunk_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5880 STAT_SET( IE_DISABLECHUNKING, fx->Parameter1 );
5881 return FX_APPLIED;
5883 //0x128 Protection:Animation
5884 int fx_protection_from_animation (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5886 if (0) printf( "fx_protection_from_animation (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5887 //remove vvc from actor if active
5888 target->RemoveVVCell(fx->Resource, false);
5889 return FX_APPLIED;
5891 //0x129 Protection:Turn
5892 int fx_protection_from_turn (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5894 if (0) printf( "fx_non_interruptible_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5895 STAT_SET( IE_NOTURNABLE, fx->Parameter1 );
5896 return FX_APPLIED;
5898 //0x12a CutScene2
5899 //runs a predetermined script in cutscene mode
5900 int fx_cutscene2 (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
5902 Game *game;
5903 ieResRef resref;
5905 if (0) printf( "fx_cutscene2 (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 );
5906 if (core->InCutSceneMode()) return FX_NOT_APPLIED;
5907 game = core->GetGame();
5908 if (!game) return FX_NOT_APPLIED;
5910 for (int i = 0; i < game->GetPartySize(false); i++) {
5911 Actor* act = game->GetPC( i, false );
5912 GAMLocationEntry *gle = game->GetPlaneLocationEntry(i);
5913 if (act && gle) {
5914 gle->Pos = act->Pos;
5915 memcpy(gle->AreaResRef, act->Area, 9);
5919 core->SetCutSceneMode(true);
5921 //GemRB enhancement: allow a custom resource
5922 if (fx->Parameter2) {
5923 strnlwrcpy(resref,fx->Resource, 8);
5924 } else {
5925 strnlwrcpy(resref,"cut250a",8);
5928 GameScript* gs = new GameScript( resref, game );
5929 gs->EvaluateAllBlocks();
5930 delete( gs );
5931 //for safety reasons, i get this pointer again
5932 game = core->GetGame();
5933 if (game) {
5934 game->ClearCutsceneID();
5936 return FX_NOT_APPLIED;
5938 //0x12b ChaosShieldModifier
5939 int fx_chaos_shield_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5941 if (0) printf( "fx_chaos_shield_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5942 STAT_MOD( IE_CHAOSSHIELD );
5943 if (fx->Parameter2) {
5944 target->AddPortraitIcon(PI_CSHIELD); //162
5945 } else {
5946 target->AddPortraitIcon(PI_CSHIELD2); //163
5948 return FX_APPLIED;
5950 //0x12c NPCBump
5951 int fx_npc_bump (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5953 if (0) printf( "fx_npc_bump (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5954 //unknown effect, but known stat position
5955 STAT_MOD( IE_NPCBUMP );
5956 return FX_APPLIED;
5958 //0x12d CriticalHitModifier
5959 int fx_critical_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5961 if (0) printf( "fx_critical_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
5962 STAT_MOD( IE_CRITICALHITBONUS );
5963 return FX_APPLIED;
5965 // 0x12e CanUseAnyItem
5966 int fx_can_use_any_item_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5968 if (0) printf( "fx_can_use_any_item_modifier (%2d): Value: %d\n", fx->Opcode, fx->Parameter2 );
5970 STAT_SET( IE_CANUSEANYITEM, fx->Parameter2 );
5971 return FX_APPLIED;
5974 // 0x12f AlwaysBackstab
5975 int fx_always_backstab_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
5977 if (0) printf( "fx_always_backstab_modifier (%2d): Value: %d\n", fx->Opcode, fx->Parameter2 );
5979 STAT_SET( IE_ALWAYSBACKSTAB, fx->Parameter2 );
5980 return FX_APPLIED;
5983 // 0x130 MassRaiseDead
5984 int fx_mass_raise_dead (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
5986 if (0) printf( "fx_mass_raise_dead (%2d)\n", fx->Opcode );
5988 Game *game=core->GetGame();
5990 int i=game->GetPartySize(false);
5991 while (i--) {
5992 Actor *actor=game->GetPC(i,false);
5993 actor->Resurrect();
5995 return FX_NOT_APPLIED;
5998 // 0x131 OffhandHitModifier
5999 int fx_left_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6001 if (0) printf( "fx_left_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
6003 STAT_MOD( IE_HITBONUSLEFT );
6004 return FX_APPLIED;
6007 // 0x132 RightHitModifier
6008 int fx_right_to_hit_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6010 if (0) printf( "fx_right_to_hit_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
6012 STAT_MOD( IE_HITBONUSRIGHT );
6013 return FX_APPLIED;
6016 // 0x133 Reveal:Tracks
6017 int fx_reveal_tracks (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6019 if (0) printf( "fx_reveal_tracks (%2d): Distance: %d\n", fx->Opcode, fx->Parameter1 );
6020 Map *map = target->GetCurrentArea();
6021 if (!map) return FX_APPLIED;
6022 if (!fx->Parameter2) {
6023 fx->Parameter2=1;
6024 //write tracks.2da entry
6025 if (map->DisplayTrackString(target)) {
6026 return FX_NOT_APPLIED;
6029 GameControl *gc = core->GetGameControl();
6030 if (gc) {
6031 //highlight all living creatures (not in party, but within range)
6032 gc->SetTracker(target, fx->Parameter1);
6034 return FX_APPLIED;
6037 // 0x134 Protection:Tracking
6038 int fx_protection_from_tracking (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6040 if (0) printf( "fx_protection_from_tracking (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 );
6042 STAT_MOD( IE_NOTRACKING ); //highlight creature???
6043 return FX_APPLIED;
6045 // 0x135 ModifyLocalVariable
6046 int fx_modify_local_variable (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6048 //convert it to internal variable format
6049 if (!fx->IsVariable) {
6050 char *poi = fx->Resource+8;
6051 memmove(poi, fx->Resource2, 8);
6052 poi+=8;
6053 memmove(poi, fx->Resource3, 8);
6054 poi+=8;
6055 memmove(poi, fx->Resource4, 8);
6056 fx->IsVariable=1;
6058 if (0) printf( "fx_modify_local_variable (%2d): %s, Mod: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 );
6059 if (fx->Parameter2) {
6060 ieDword var = 0;
6061 //use resource memory area as variable name
6062 target->locals->Lookup(fx->Resource, var);
6063 target->locals->SetAt(fx->Resource, var+fx->Parameter1);
6064 } else {
6065 target->locals->SetAt(fx->Resource, fx->Parameter1);
6067 return FX_NOT_APPLIED;
6070 // 0x136 TimelessState
6071 int fx_timeless_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6073 if (0) printf( "fx_timeless_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter2 );
6074 STAT_SET(IE_DISABLETIMESTOP, fx->Parameter2);
6075 return FX_APPLIED;
6078 //0x137 GenerateWish
6079 #define WISHCOUNT 25
6080 static int wishlevels[WISHCOUNT]={10,10,10,10,0,10,0,15,0,0,0,0,0,0,15,0,0,
6081 17,9,17,17,9,9,9,0};
6083 int fx_generate_wish (Scriptable* Owner, Actor* target, Effect* fx)
6085 ieResRef spl;
6087 if (0) printf( "fx_generate_wish (%2d): Mod: %d\n", fx->Opcode, fx->Parameter2 );
6088 int tmp = core->Roll(1,WISHCOUNT,0);
6089 sprintf(spl,"SPWISH%02d",tmp);
6090 core->ApplySpell(spl, target, Owner, wishlevels[tmp-1]);
6091 return FX_NOT_APPLIED;
6093 //0x138 //see fx_crash, this effect is not fully enabled in original bg2/tob
6094 int fx_immunity_sequester (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6096 if (0) printf( "fx_immunity_sequester (%2d): Mod: %d\n", fx->Opcode, fx->Parameter2 );
6097 //this effect is supposed to provide immunity against sequester (maze/etc?)
6098 STAT_SET(IE_NOSEQUESTER, fx->Parameter2);
6099 return FX_APPLIED;
6102 //0x139 //HLA generic effect
6103 //0x13a StoneSkin2Modifier
6104 int fx_golem_stoneskin_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6106 if (0) printf( "fx_golem_stoneskin_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 );
6107 if (!fx->Parameter1) {
6108 return FX_NOT_APPLIED;
6110 //dead actors lose this effect
6111 if (STATE_GET( STATE_DEAD) ) {
6112 return FX_NOT_APPLIED;
6115 STAT_SET(IE_STONESKINSGOLEM, fx->Parameter1);
6116 SetGradient(target, 14);
6117 return FX_APPLIED;
6120 // 0x13b AvatarRemovalModifier (also 0x104 iwd)
6121 int fx_avatar_removal_modifier (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6123 if (0) printf( "fx_avatar_removal_modifier (%2d): Mod: %d\n", fx->Opcode, fx->Parameter2 );
6124 STAT_SET(IE_AVATARREMOVAL, fx->Parameter2);
6125 return FX_APPLIED;
6127 // 0x13c MagicalRest (also 0x124 iwd)
6128 int fx_magical_rest (Scriptable* /*Owner*/, Actor* target, Effect* fx)
6130 if (0) printf( "fx_magical_rest (%2d)\n", fx->Opcode );
6131 //instant, full rest
6132 target->Rest(0);
6133 target->fxqueue.RemoveAllEffectsWithParam(fx_display_portrait_icon_ref, PI_FATIGUE);
6134 return FX_NOT_APPLIED;
6137 // 0x13d ImprovedHaste (See 0x10 Haste)
6138 // unknown
6139 int fx_unknown (Scriptable* /*Owner*/, Actor* /*target*/, Effect* fx)
6141 printf( "fx_unknown (%2d): P1: %d P2: %d ResRef: %s\n", fx->Opcode, fx->Parameter1, fx->Parameter2, fx->Resource );
6142 return FX_NOT_APPLIED;
6145 #include "plugindef.h"
6147 GEMRB_PLUGIN(0x1AAA040A, "Effect opcodes for core games")
6148 PLUGIN_INITIALIZER(RegisterCoreOpcodes)
6149 PLUGIN_CLEANUP(Cleanup)
6150 END_PLUGIN()