From: <ave...@us...> - 2007-11-04 16:48:07
|
Revision: 4809 http://gemrb.svn.sourceforge.net/gemrb/?rev=4809&view=rev Author: avenger_teambg Date: 2007-11-04 08:48:08 -0800 (Sun, 04 Nov 2007) Log Message: ----------- small changes in effect plugins Modified Paths: -------------- gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp gemrb/trunk/gemrb/plugins/PSTOpcodes/PSTOpc.cpp Modified: gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp 2007-11-04 16:27:11 UTC (rev 4808) +++ gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp 2007-11-04 16:48:08 UTC (rev 4809) @@ -1127,6 +1127,8 @@ case 256: damagetype = DAMAGE_ELECTRICITY; break; + case 512: + default: damagetype = DAMAGE_ACID; } @@ -1149,7 +1151,6 @@ #define CSA_DEX 0 #define CSA_STR 1 - #define CSA_CNT 2 int SpellAbilityDieRoll(Actor *target, int which) { @@ -1265,7 +1266,7 @@ // 2,5 are the same int fx_maximum_hp_modifier (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_maximum_hp_modifier (%2d): Stat Modif: %d ; Modif Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (0) printf( "fx_maximum_hp_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); bool base = fx->TimingMode==FX_DURATION_INSTANT_PERMANENT; @@ -1278,7 +1279,7 @@ } else { STAT_ADD( IE_MAXHITPOINTS, fx->Parameter1 ); if (fx->FirstApply) { - BASE_ADD( IE_HITPOINTS, fx->Parameter1 ); + BASE_ADD( IE_HITPOINTS, fx->Parameter1 ); } } break; @@ -1385,7 +1386,7 @@ // 0x18 State:Panic int fx_set_panic_state (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_set_panic_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (0) printf( "fx_set_panic_state (%2d)\n", fx->Opcode ); if (target->HasSpellState(SS_BLOODRAGE)) { return FX_NOT_APPLIED; @@ -1448,7 +1449,7 @@ // gemrb extension: if the resource field is filled, it will remove curse only from the specified item int fx_remove_curse (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_remove_curse (%2d): Resource: %s\n", fx->Opcode, fx->Resource ); + if (0) printf( "fx_remove_curse (%2d): Resource: %s Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 ); switch(fx->Parameter2) { @@ -1532,7 +1533,6 @@ if (0) printf( "fx_cure_dead_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); //someone should clear the internal flags related to death target->Resurrect(); - //STATE_CURE( STATE_DEAD ); return FX_NOT_APPLIED; } @@ -1584,7 +1584,7 @@ // 0x26 State:Silenced int fx_set_silenced_state (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_set_silenced_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (0) printf( "fx_set_silenced_state (%2d)\n", fx->Opcode ); STATE_SET( STATE_SILENCED ); return FX_APPLIED; } @@ -1594,26 +1594,31 @@ // 0x27 State:Helpless // this effect sets both bits, but 'awaken' only removes the sleep bit // FIXME: this is probably a persistent effect -int fx_set_unconscious_state (Actor* /*Owner*/, Actor* target, Effect* fx) +int fx_set_unconscious_state (Actor* Owner, Actor* target, Effect* fx) { - if (0) printf( "fx_set_unconscious_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (0) printf( "fx_set_unconscious_state (%2d): Type: %d\n", fx->Opcode, fx->Parameter2 ); if (target->HasSpellState(SS_BLOODRAGE)) { return FX_NOT_APPLIED; } - target->SetStance(IE_ANI_SLEEP); - if (fx->Parameter2) { + if (fx->FirstApply) { + Effect *newfx; + + newfx = EffectQueue::CreateEffectCopy(fx, fx_animation_stance_ref, 0, IE_ANI_SLEEP); + core->ApplyEffect(newfx, target, Owner); + } + + if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) { BASE_STATE_SET( STATE_HELPLESS | STATE_SLEEP ); //don't awaken on damage - //the effect directly sets the state bit, and doesn't stick - fx->Opcode=EffectQueue::ResolveEffect(fx_animation_stance_ref); - //convert effect to awaken - EffectQueue::TransformToDelay(fx->TimingMode); - //apply cure helpless timed - return FX_APPLIED; + } else { + STATE_SET( STATE_HELPLESS | STATE_SLEEP ); //don't awaken on damage + if (fx->Parameter2) { + target->SetSpellState(SS_NOAWAKE); + } + target->AddPortraitIcon(PI_SLEEP); } - BASE_STATE_SET( STATE_SLEEP ); //awaken on damage - return FX_NOT_APPLIED; + return FX_PERMANENT; } // 0x28 State:Slowed @@ -1735,6 +1740,10 @@ { if (0) printf( "fx_set_stun_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if ( STATE_GET(STATE_DEAD) ) { + return FX_NOT_APPLIED; + } + if (target->HasSpellState(SS_BLOODRAGE)) { return FX_NOT_APPLIED; } @@ -1882,7 +1891,7 @@ fx->Opcode = EffectQueue::ResolveEffect(fx_death_ref); fx->TimingMode = FX_DURATION_INSTANT_PERMANENT; fx->Parameter1 = 0; - fx->Parameter2 = 0; + fx->Parameter2 = 4; return FX_APPLIED; } //doesn't stick @@ -3175,6 +3184,7 @@ if (STATE_GET (STATE_HOLY) ) //holy power is non cumulative return FX_NOT_APPLIED; STATE_SET( STATE_HOLY ); + //setting the spell state to be compatible with iwd2 target->SetSpellState(SS_HOLYMIGHT); STAT_ADD( IE_STR, fx->Parameter1); STAT_ADD( IE_CON, fx->Parameter1); @@ -3282,14 +3292,15 @@ if (cgcount<0) { cgcount = core->ReadResRefTable("cgtable",casting_glows); } - //delay apply until map is loaded + //remove effect if map is not loaded Map *map = target->GetCurrentArea(); if (!map) { - return FX_APPLIED; + return FX_NOT_APPLIED; } if (fx->Parameter2<(ieDword) cgcount) { ScriptedAnimation *sca = core->GetScriptedAnimation(casting_glows[fx->Parameter2], false); + //remove effect if animation doesn't exist if (!sca) { return FX_NOT_APPLIED; } @@ -3317,13 +3328,14 @@ if (shcount<0) { shcount = core->ReadResRefTable("shtable",spell_hits); } - //delay apply until map is loaded + //remove effect if map is not loaded Map *map = target->GetCurrentArea(); if (!map) { - return FX_APPLIED; + return FX_NOT_APPLIED; } if (fx->Parameter2<(ieDword) shcount) { ScriptedAnimation *sca = core->GetScriptedAnimation(spell_hits[fx->Parameter2], false); + //remove effect if animation doesn't exist if (!sca) { return FX_NOT_APPLIED; } @@ -4181,7 +4193,8 @@ int fx_select_spell (Actor* /*Owner*/, Actor* /*target*/, Effect* fx) { if (0) printf( "fx_select_spell (%2d) %d\n", fx->Opcode, fx->Parameter2 ); - //if parameter2==0 -> + //if parameter2==0 -> cast spells from 2da (all spells listed in 2da) + //if parameter2==1 -> cast spells from book (all known spells, no need of memorize) return FX_NOT_APPLIED; } @@ -4189,9 +4202,16 @@ int fx_play_visual_effect (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_play_visual_effect (%2d): Resource: %s Type: %d\n", fx->Opcode, fx->Resource, fx->Parameter2 ); - if (!fx->Resource[0]) { + + //this is in the original engine (dead actors lose this effect) + if (STATE_GET( STATE_DEAD) ) { return FX_NOT_APPLIED; } + + //delay action until area is loaded to avoid crash + Map *map = target->GetCurrentArea(); + if (!map) return FX_APPLIED; + //if it is sticky, don't add it if it is already played if (fx->Parameter2) { if (!target->HasVVCCell(fx->Resource) ) { @@ -4200,6 +4220,12 @@ } ScriptedAnimation* sca = core->GetScriptedAnimation(fx->Resource, false); + + //don't crash on nonexistent resources + if (!sca) { + return FX_NOT_APPLIED; + } + if (fx->TimingMode!=FX_DURATION_INSTANT_PERMANENT) { sca->SetDefaultDuration(fx->Duration-core->GetGame()->Ticks); } @@ -4212,7 +4238,7 @@ //not sticky sca->XPos=fx->PosX; sca->YPos=fx->PosY; - target->GetCurrentArea()->AddVVCell( sca ); + map->AddVVCell( sca ); return FX_NOT_APPLIED; } @@ -4279,14 +4305,14 @@ //0xDC DispelSchool int fx_dispel_school (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_dispel_school (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 ); + if (0) printf( "fx_dispel_school (%2d): Level: %d Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); target->fxqueue.RemoveLevelEffects(fx->Parameter1, RL_MATCHSCHOOL, fx->Parameter2); return FX_NOT_APPLIED; } //0xDD DispelSecondaryType int fx_dispel_secondary_type (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_dispel_secondary_type (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 ); + if (0) printf( "fx_dispel_secondary_type (%2d): Level: %d Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); target->fxqueue.RemoveLevelEffects(fx->Parameter1, RL_MATCHSECTYPE, fx->Parameter2); return FX_NOT_APPLIED; } @@ -4294,7 +4320,12 @@ //0xDE RandomTeleport int fx_teleport_field (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_teleport_field (%2d): Mod: %d\n", fx->Opcode, fx->Parameter1 ); + if (0) printf( "fx_teleport_field (%2d): Distance: %d\n", fx->Opcode, fx->Parameter1 ); + + Map *map = target->GetCurrentArea(); + if (!map) { + return FX_NOT_APPLIED; + } //this should be the target's position, i think Point p = target->Pos; p.x+=core->Roll(1,fx->Parameter1*2,-(signed) (fx->Parameter1)); @@ -4525,13 +4556,16 @@ } // 0xee Disintegrate -int fx_disintegrate (Actor* Owner, Actor* target, Effect* fx) +int fx_disintegrate (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_disintegrate (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); if (EffectQueue::match_ids( target, fx->Parameter1, fx->Parameter2) ) { - target->Damage(0, fx->Parameter2, Owner); //hmm? - //death has damage type too - target->Die(Owner); + //convert it to a death opcode or apply the new effect? + fx->Opcode = EffectQueue::ResolveEffect(fx_death_ref); + fx->TimingMode = FX_DURATION_INSTANT_PERMANENT; + fx->Parameter1 = 0; + fx->Parameter2 = 0x200; + return FX_APPLIED; } return FX_NOT_APPLIED; } Modified: gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp 2007-11-04 16:27:11 UTC (rev 4808) +++ gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp 2007-11-04 16:48:08 UTC (rev 4809) @@ -39,7 +39,8 @@ static int shcount = -1; //a scripting object for enemy (used for enemy in line of sight check) static Trigger *Enemy = NULL; -static ieDword *projectilelist = NULL; +//a list of projectiles Entropy Shield protects against +static ieDword *EntropyProjectileList = NULL; #define PI_CONFUSION 3 #define PI_PROTFROMEVIL 9 @@ -354,10 +355,10 @@ } Enemy=NULL; - if (projectilelist) { - free (projectilelist); + if (EntropyProjectileList) { + free (EntropyProjectileList); } - projectilelist = NULL; + EntropyProjectileList = NULL; } //iwd got a weird targeting system @@ -367,7 +368,7 @@ //this is partly superior, partly inferior to the bioware //ids targeting. //superior because it can handle other stats and conditions -//inferior because it is not moddable +//inferior because it is not so readily moddable //The hardcoded conditions are simulated via the IWDIDSEntry //structure. //stat is usually a stat, but for special conditions it is a @@ -514,6 +515,8 @@ delete newfx; } +//this function implements AC bonus handling +//ReverseToHit is the 2nd ed way of AC (lower is better) static inline void HandleBonus(Actor *target, int stat, int mod, int mode) { if (mode==FX_DURATION_INSTANT_PERMANENT) { @@ -582,6 +585,7 @@ // 0x84 DrawUponHolyMight // this effect differs from bg2 because it doesn't use the actor state field // it uses the spell state field +// in bg2 the effect is called: HolyNonCumulative int fx_draw_upon_holy_might (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_draw_upon_holy_might (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); @@ -627,7 +631,7 @@ //0xe8 Colour:FadeRGB int fx_fade_rgb (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_fade_rgb (%2d): \n", fx->Opcode ); + if (0) printf( "fx_fade_rgb (%2d): RGB:%x\n", fx->Opcode, fx->Parameter1 ); int speed = (fx->Parameter2 >> 16) & 0xFF; target->SetColorMod(0xff, RGBModifier::ADD, speed, @@ -644,13 +648,15 @@ if (shcount<0) { shcount = core->ReadResRefTable("iwdshtab",iwd_spell_hits); } - //delay apply until map is loaded + + //remove effect if there is no current area Map *map = target->GetCurrentArea(); if (!map) { - return FX_APPLIED; + return FX_NOT_APPLIED; } if (fx->Parameter2<(ieDword) shcount) { ScriptedAnimation *sca = core->GetScriptedAnimation(iwd_spell_hits[fx->Parameter2], false); + //remove effect if there is no animation if (!sca) { return FX_NOT_APPLIED; } @@ -682,7 +688,7 @@ return FX_NOT_APPLIED; } -//0xeb CastingGlow2 will be same as original casting glow +//0xeb CastingGlow2 will be same as original casting glow (iwd2 does the same) //0xec ChillTouch (how) //this effect is to simulate the composite effects of chill touch @@ -1589,6 +1595,17 @@ { if (0) printf( "fx_soul_eater (%2d): Damage %d\n", fx->Opcode, fx->Parameter1 ); target->Damage(fx->Parameter1, DAMAGE_SOULEATER, Owner); + if (STATE_GET(STATE_DEAD) ) { + ieResRef monster; + ieResRef hit; + ieResRef areahit; + + //todo: supply the souleatr.2da file + core->GetResRefFrom2DA("souleatr", monster, hit, areahit); + //the monster should appear near the effect position + Point p(fx->PosX, fx->PosY); + core->SummonCreature(monster, areahit, Owner, target, p, -1, fx->Parameter1); + } return FX_NOT_APPLIED; } @@ -2394,7 +2411,7 @@ if (0) printf( "fx_free_action_iwd2 (%2d)\n", fx->Opcode); if (target->SetSpellState( SS_FREEACTION)) return FX_APPLIED; - // immunity to the following effects: + // immunity to the following effects, coded in the effects: // 0x9a Overlay:Entangle, ok // 0x9d Overlay:Web ok // 0x9e Overlay:Grease ok @@ -2409,9 +2426,10 @@ } //419 Unconsciousness +//same as the sleep effect, but different icon int fx_unconsciousness (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_unconsciousness (%2d)\n", fx->Opcode); + if (0) printf( "fx_unconsciousness (%2d): Type: %d\n", fx->Opcode, fx->Parameter2); STATE_SET(STATE_HELPLESS|STATE_SLEEP); if (fx->Parameter2) { target->SetSpellState(SS_NOAWAKE); @@ -2426,17 +2444,18 @@ //420 Death2 (see in core effects) //421 EntropyShield - int fx_entropy_shield (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_entropy_shield (%2d)\n", fx->Opcode); if (target->SetSpellState( SS_ENTROPY)) return FX_APPLIED; //immunity to certain projectiles - if (!projectilelist) { - projectilelist = core->GetListFrom2DA("entropy"); - ieDword i = projectilelist[0]; + if (!EntropyProjectileList) { + EntropyProjectileList = core->GetListFrom2DA("entropy"); + ieDword i = EntropyProjectileList[0]; + //the index is handled differently because + //the list's first element is the element count while(i) { - target->AddProjectileImmunity(projectilelist[i--]); + target->AddProjectileImmunity(EntropyProjectileList[i--]); } } if (enhanced_effects) { Modified: gemrb/trunk/gemrb/plugins/PSTOpcodes/PSTOpc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/PSTOpcodes/PSTOpc.cpp 2007-11-04 16:27:11 UTC (rev 4808) +++ gemrb/trunk/gemrb/plugins/PSTOpcodes/PSTOpc.cpp 2007-11-04 16:48:08 UTC (rev 4809) @@ -26,6 +26,7 @@ #include "../Core/EffectQueue.h" #include "../Core/Interface.h" #include "../Core/Video.h" //for tints +#include "../Core/TileMap.h" #include "PSTOpc.h" @@ -422,7 +423,10 @@ int fx_move_view (Actor* /*Owner*/, Actor* /*target*/, Effect* fx) { if (0) printf( "fx_move_view (%2d): Speed: %d\n", fx->Opcode, fx->Parameter1 ); - core->timer->SetMoveViewPort( fx->PosX, fx->PosY, fx->Parameter1, true); + Map *map = core->GetGame()->GetCurrentArea(); + if (map) { + core->timer->SetMoveViewPort( fx->PosX, fx->PosY, fx->Parameter1, true); + } return FX_NOT_APPLIED; } @@ -435,18 +439,18 @@ STATE_SET( STATE_EMBALM ); if (!fx->Parameter1) { if (fx->Parameter2) { - fx->Parameter1=fx->Power*2; + fx->Parameter1=fx->CasterLevel*2; } else { fx->Parameter1=core->Roll(1,6,1); } BASE_ADD( IE_HITPOINTS, fx->Parameter1 ); } + STAT_ADD( IE_MAXHITPOINTS, fx->Parameter1); if (fx->Parameter2) { STAT_ADD( IE_ARMORCLASS,2 ); } else { STAT_ADD( IE_ARMORCLASS,1 ); } - //set global flag return FX_APPLIED; } //0xcf fx_stop_all_action This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |