From: <ave...@us...> - 2007-10-22 19:46:13
|
Revision: 4804 http://gemrb.svn.sourceforge.net/gemrb/?rev=4804&view=rev Author: avenger_teambg Date: 2007-10-22 12:45:58 -0700 (Mon, 22 Oct 2007) Log Message: ----------- Implemented weapon immunity Implemented some effect relations (aegis, berserk, etc) Implemented 800x600 PST game area option Modified Paths: -------------- gemrb/trunk/gemrb/GUIScripts/pst/GUIWORLD.py gemrb/trunk/gemrb/GUIScripts/pst/MessageWindow.py gemrb/trunk/gemrb/includes/ie_stats.h gemrb/trunk/gemrb/plugins/Core/Actor.cpp gemrb/trunk/gemrb/plugins/Core/Actor.h gemrb/trunk/gemrb/plugins/Core/EffectQueue.cpp gemrb/trunk/gemrb/plugins/Core/EffectQueue.h gemrb/trunk/gemrb/plugins/Core/GSUtils.cpp gemrb/trunk/gemrb/plugins/Core/GameScript.h gemrb/trunk/gemrb/plugins/Core/Triggers.cpp gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp Added Paths: ----------- gemrb/trunk/gemrb/override/pst/guiw08.chu gemrb/trunk/gemrb/override/pst/wmmos2b.mos Modified: gemrb/trunk/gemrb/GUIScripts/pst/GUIWORLD.py =================================================================== --- gemrb/trunk/gemrb/GUIScripts/pst/GUIWORLD.py 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/GUIScripts/pst/GUIWORLD.py 2007-10-22 19:45:58 UTC (rev 4804) @@ -61,7 +61,7 @@ hideflag = GemRB.HideGUI () - GemRB.LoadWindowPack ("GUIWORLD") + GemRB.LoadWindowPack (GetWindowPack()) ContainerWindow = Window = GemRB.LoadWindow (8) DisableAnimatedWindows () GemRB.SetVar ("ActionsWindow", Window) @@ -262,7 +262,7 @@ return GemRB.HideGUI () - GemRB.LoadWindowPack ("GUIWORLD") + GemRB.LoadWindowPack (GetWindowPack()) ReformPartyWindow = Window = GemRB.LoadWindow (24) GemRB.SetVar ("OtherWindow", Window) DisableAnimatedWindows () @@ -297,7 +297,7 @@ return GemRB.HideGUI () - GemRB.LoadWindowPack ("GUIWORLD") + GemRB.LoadWindowPack (GetWindowPack()) FormationWindow = Window = GemRB.LoadWindow (27) GemRB.SetVar ("OtherWindow", Window) DisableAnimatedWindows () @@ -348,3 +348,11 @@ GemRB.SetButtonState (Window, Button, IE_GUI_BUTTON_SELECTED) last_formation = formation + + +def GetWindowPack(): + width = GemRB.GetSystemVariable (SV_WIDTH) + if width == 800: + return "GUIW08" + #default + return "GUIWORLD" Modified: gemrb/trunk/gemrb/GUIScripts/pst/MessageWindow.py =================================================================== --- gemrb/trunk/gemrb/GUIScripts/pst/MessageWindow.py 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/GUIScripts/pst/MessageWindow.py 2007-10-22 19:45:58 UTC (rev 4804) @@ -51,7 +51,7 @@ GemRB.GameSetPartySize(PARTY_SIZE) GemRB.GameSetProtagonistMode(0) - GemRB.LoadWindowPack ("GUIWORLD") + GemRB.LoadWindowPack (GetWindowPack()) GemRB.SetInfoTextColor(0,255,0,255) ActionsWindow = GemRB.LoadWindow(0) OptionsWindow = GemRB.LoadWindow(2) Modified: gemrb/trunk/gemrb/includes/ie_stats.h =================================================================== --- gemrb/trunk/gemrb/includes/ie_stats.h 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/includes/ie_stats.h 2007-10-22 19:45:58 UTC (rev 4804) @@ -140,6 +140,7 @@ #define EXTSTATE_EYE_STONE 0x00000400 #define EXTSTATE_NO_BACKSTAB 0x00004000 #define EXTSTATE_DEAF 0x00020000 +#define EXTSTATE_NO_WAKEUP 0x80000000 //original HoW engine put this on top of eye_mind #define EXTSTATE_SEVEN_EYES 0x000007f0 //Multiclass flags Added: gemrb/trunk/gemrb/override/pst/guiw08.chu =================================================================== (Binary files differ) Property changes on: gemrb/trunk/gemrb/override/pst/guiw08.chu ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: gemrb/trunk/gemrb/override/pst/wmmos2b.mos =================================================================== (Binary files differ) Property changes on: gemrb/trunk/gemrb/override/pst/wmmos2b.mos ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: gemrb/trunk/gemrb/plugins/Core/Actor.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/Core/Actor.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/Actor.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -1612,10 +1612,19 @@ } } +static EffectRef fx_cure_sleep_ref={"Cure:Sleep",NULL,-1}; + void Actor::GetHit() { SetStance( IE_ANI_DAMAGE ); DisplayStringCore(this, VB_DAMAGE, DS_CONSOLE|DS_CONST ); + if (Modified[IE_STATE_ID]&STATE_SLEEP) { + if (Modified[IE_EXTSTATE_ID]&EXTSTATE_NO_WAKEUP) { + return; + } + Effect *fx = EffectQueue::CreateEffect(fx_cure_sleep_ref, 0, 0, FX_DURATION_INSTANT_PERMANENT); + fxqueue.AddEffect(fx); + } } bool Actor::HandleCastingStance(const ieResRef SpellResRef, bool deplete) @@ -2236,7 +2245,7 @@ } //slot is the projectile slot -int Actor::GetRangedWeapon(ITMExtHeader *&which) const +int Actor::GetRangedWeapon(ITMExtHeader *&which, WeaponInfo *wi) const { unsigned int slot = inventory.FindRangedWeapon(); const CREItem *wield = inventory.GetSlotItem(slot); @@ -2247,6 +2256,10 @@ if (!item) { return 0; } + if (wi) { + wi->enchantment = item->Enchantment; + wi->itemflags = wield->Flags; + } which = item->GetWeaponHeader(true); core->FreeItem(item, wield->ItemResRef, false); return 0; @@ -2254,7 +2267,7 @@ //returns weapon header currently used //if range is nonzero, then the returned header is valid -unsigned int Actor::GetWeapon(ITMExtHeader *&which, bool leftorright) const +unsigned int Actor::GetWeapon(ITMExtHeader *&which, WeaponInfo *wi, bool leftorright) const { const CREItem *wield = inventory.GetUsedWeapon(leftorright); if (!wield) { @@ -2265,6 +2278,10 @@ return 0; } + if (wi) { + wi->enchantment = item->Enchantment; + wi->itemflags = wield->Flags; + } //select first weapon header which = item->GetWeaponHeader(false); //make sure we use 'false' in this freeitem @@ -2535,9 +2552,11 @@ } //which hand is used bool leftorright = (bool) (attackcount&1); + + WeaponInfo wi; ITMExtHeader *header; //can't reach target, zero range shouldn't be allowed - if (GetWeapon(header,leftorright)*10<PersonalDistance(this, target)+1) { + if (GetWeapon(header, &wi, leftorright)*10<PersonalDistance(this, target)+1) { return; } ieDword Flags; @@ -2550,7 +2569,7 @@ Flags = WEAPON_RANGED; break; case ITEM_AT_BOW: - if (!GetRangedWeapon(rangedheader)) { + if (!GetRangedWeapon(rangedheader, &wi)) { //out of ammo event //try to refill SetStance(IE_ANI_READY); @@ -2571,6 +2590,7 @@ int roll = core->Roll(1,ATTACKROLL,0); if (roll==1) { + DisplayStringCore(this, VB_CRITMISS, DS_CONSOLE|DS_CONST ); //critical failure return; } @@ -2587,7 +2607,8 @@ if (roll>=ATTACKROLL-(int) GetStat(IE_CRITICALHITBONUS) ) { //critical success - DealDamage (target, damage, damagetype, true); + DisplayStringCore(this, VB_CRITHIT, DS_CONSOLE|DS_CONST ); + DealDamage (target, damage, damagetype, &wi, true); return; } tohit += roll; @@ -2603,7 +2624,7 @@ //hit failed return; } - DealDamage (target, damage, damagetype, false); + DealDamage (target, damage, damagetype, &wi, false); } static const int weapon_damagetype[] = {DAMAGE_CRUSHING, DAMAGE_PIERCING, @@ -2612,12 +2633,14 @@ static EffectRef fx_stoneskin_ref={"StoneSkinModifier",NULL,-1}; static EffectRef fx_stoneskin2_ref={"StoneSkin2Modifier",NULL,-1}; static EffectRef fx_mirrorimage_ref={"MirrorImageModifier",NULL,-1}; +static EffectRef fx_aegis_ref={"Aegis",NULL,-1}; -void Actor::DealDamage(Actor *target, int damage, int damagetype, bool critical) +void Actor::DealDamage(Actor *target, int damage, int damagetype, WeaponInfo *wi, bool critical) { int stoneskins = target->Modified[IE_STONESKINS]; if (stoneskins) { target->fxqueue.DecreaseParam1OfEffect(fx_stoneskin_ref, 1); + target->fxqueue.DecreaseParam1OfEffect(fx_aegis_ref, 1); target->Modified[IE_STONESKINS]--; return; } @@ -2638,7 +2661,19 @@ } } + if (target->fxqueue.WeaponImmunity(wi->enchantment, wi->itemflags)) { + damage = 0; + } + if (damage<0) damage = 0; + + //check casting failure + + if (!damage) { + DisplayStringCore(this, VB_TIMMUNE, DS_CONSOLE|DS_CONST ); + return; + } + if (critical) { //a critical surely raises the morale? NewBase(IE_MORALE, 1, MOD_ADDITIVE); @@ -3788,6 +3823,16 @@ return false; } +//returns true if spell state is already set +bool Actor::HasSpellState(unsigned int spellstate) +{ + if (spellstate>=192) return false; + unsigned int pos = IE_SPLSTATE_ID1+(spellstate>>5); + unsigned int bit = 1<<(spellstate&31); + if (Modified[pos]&bit) return true; + return false; +} + //returns the numeric value of a feat, different from HasFeat //for multiple feats int Actor::GetFeat(unsigned int feat) const Modified: gemrb/trunk/gemrb/plugins/Core/Actor.h =================================================================== --- gemrb/trunk/gemrb/plugins/Core/Actor.h 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/Actor.h 2007-10-22 19:45:58 UTC (rev 4804) @@ -117,6 +117,11 @@ typedef std::vector< ScriptedAnimation*> vvcVector; typedef std::list<ieResRef*> resourceList; +typedef struct { + int enchantment; + ieDword itemflags; +} WeaponInfo; + class GEM_EXPORT Actor : public Movable { public: //CRE DATA FIELDS @@ -381,10 +386,10 @@ /* learns the given spell, possibly receive XP */ int LearnSpell(const ieResRef resref, ieDword flags); /* returns the ranged weapon header associated with the currently equipped projectile */ - int GetRangedWeapon(ITMExtHeader *&which) const; + int GetRangedWeapon(ITMExtHeader *&which, WeaponInfo *wi) const; /* Returns current weapon range and extended header if range is nonzero, then which is valid */ - unsigned int GetWeapon(ITMExtHeader *&which, bool leftorright=false) const; + unsigned int GetWeapon(ITMExtHeader *&which, WeaponInfo *wi, bool leftorright=false) const; /* Creates player statistics */ void CreateStats(); /* Heals actor by days */ @@ -404,7 +409,7 @@ /* performs attack against target */ void PerformAttack(ieDword initiative); /* deal damage to target */ - void DealDamage(Actor *target, int damage,int damagetype, bool critical); + void DealDamage(Actor *target, int damage, int damagetype, WeaponInfo *wi, bool critical); /* sets a colour gradient stat, handles location */ void SetColor( ieDword idx, ieDword grd); /* sets an RGB colour modification effect; location 0xff for global */ @@ -484,6 +489,8 @@ void SetOverlay(unsigned int overlay); /* Checks and sets a spellstate if it wasn't set yet */ bool SetSpellState(unsigned int spellstate); + /* Checks a spellstate */ + bool HasSpellState(unsigned int spellstate); /* Checks a feat */ bool HasFeat(unsigned int featindex) const; /* Reports projectile immunity, nonzero if immune */ Modified: gemrb/trunk/gemrb/plugins/Core/EffectQueue.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/Core/EffectQueue.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/EffectQueue.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -1331,6 +1331,41 @@ return BonusAgainstCreature(effect_reference.EffText, actor); } +bool EffectQueue::WeaponImmunity(ieDword opcode, int enchantment, ieDword weapontype) const +{ + std::list< Effect* >::const_iterator f; + for ( f = effects.begin(); f != effects.end(); f++ ) { + MATCH_OPCODE(); + MATCH_LIVE_FX(); + // + int magic = (int) (*f)->Parameter1; + ieDword mask = (*f)->Parameter3; + ieDword value = (*f)->Parameter4; + if (magic==0) { + if (enchantment) continue; + } else if (magic>0) { + if (enchantment>magic) continue; + } + + if ((weapontype&mask) != value) { + continue; + } + return true; + } + return false; +} + +static EffectRef fx_weapon_immunity_ref={"Protection:Weapons",NULL,-1}; + +bool EffectQueue::WeaponImmunity(int enchantment, ieDword weapontype) const +{ + ResolveEffectRef(fx_weapon_immunity_ref); + if (fx_weapon_immunity_ref.EffText<0) { + return 0; + } + return WeaponImmunity(fx_weapon_immunity_ref.EffText, enchantment, weapontype); +} + //useful for immunity vs spell, can't use item, etc. Effect *EffectQueue::HasOpcodeWithResource(ieDword opcode, const ieResRef resource) const { Modified: gemrb/trunk/gemrb/plugins/Core/EffectQueue.h =================================================================== --- gemrb/trunk/gemrb/plugins/Core/EffectQueue.h 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/EffectQueue.h 2007-10-22 19:45:58 UTC (rev 4804) @@ -228,6 +228,8 @@ static void TransformToDelay(ieDword &TimingMode); //getting summarised effects int BonusAgainstCreature(EffectRef &effect_reference, Actor *actor) const; + //getting weapon immunity flag + bool WeaponImmunity(int enchantment, ieDword weapontype) const; // returns -1 if bounced, 0 if resisted, 1 if accepted spell int CheckImmunity(Actor *target) const; @@ -256,6 +258,7 @@ Effect *HasOpcodeWithResource(ieDword opcode, const ieResRef resource) const; void DecreaseParam1OfEffect(ieDword opcode, ieDword amount) const; int BonusAgainstCreature(ieDword opcode, Actor *actor) const; + bool WeaponImmunity(ieDword opcode, int enchantment, ieDword weapontype) const; }; #endif // ! EFFECTQUEUE_H Modified: gemrb/trunk/gemrb/plugins/Core/GSUtils.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/Core/GSUtils.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/GSUtils.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -1140,7 +1140,8 @@ //if distance is too much, insert a move action and requeue the action ITMExtHeader *header; - unsigned int wrange = actor->GetWeapon(header) * 10; + + unsigned int wrange = actor->GetWeapon(header, NULL) * 10; if ( wrange == 0) { wrange = 10; } Modified: gemrb/trunk/gemrb/plugins/Core/GameScript.h =================================================================== --- gemrb/trunk/gemrb/plugins/Core/GameScript.h 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/GameScript.h 2007-10-22 19:45:58 UTC (rev 4804) @@ -42,17 +42,21 @@ #define DS_SILENT 32 //verbal constant (bg2), we need a lookup table for other games -#define VB_PANIC 1 -#define VB_TIRED 7 -#define VB_BORED 8 -#define VB_ATTACK 9 -#define VB_DAMAGE 18 -#define VB_DIE 19 -#define VB_SELECT 26 -#define VB_REACT 53 -#define VB_REACT_S 54 -#define VB_HOSTILE 59 -#define VB_DIALOG 60 +#define VB_PANIC 1 +#define VB_TIRED 7 +#define VB_BORED 8 +#define VB_ATTACK 9 +#define VB_DAMAGE 18 +#define VB_DIE 19 +#define VB_SELECT 26 +#define VB_REACT 53 +#define VB_REACT_S 54 +#define VB_HOSTILE 59 +#define VB_DIALOG 60 +#define VB_CRITHIT 65 +#define VB_CRITMISS 66 +#define VB_TIMMUNE 67 +#define VB_INVENTORY 68 //diffmode (iwd2) #define DM_EQUAL 1 Modified: gemrb/trunk/gemrb/plugins/Core/Triggers.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/Core/Triggers.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/Core/Triggers.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -3430,8 +3430,8 @@ } Actor *actor = (Actor *) Sender; ITMExtHeader *header; - unsigned int wrange = actor->GetWeapon(header, false) * 10; - unsigned int wrange2 = actor->GetWeapon(header, true) * 10; + unsigned int wrange = actor->GetWeapon(header, NULL, false) * 10; + unsigned int wrange2 = actor->GetWeapon(header, NULL, true) * 10; if (wrange2>wrange) { wrange=wrange2; } @@ -3457,7 +3457,7 @@ } Actor *actor = (Actor *) scr; ITMExtHeader *header; - unsigned int weapon = actor->GetWeapon(header); + unsigned int weapon = actor->GetWeapon(header, NULL); //no weapon wielded? if (weapon==0) { return 0; @@ -3486,7 +3486,7 @@ } Actor *actor = (Actor *) Sender; ITMExtHeader *header; - unsigned int weapon = actor->GetWeapon(header); + unsigned int weapon = actor->GetWeapon(header, NULL); //no weapon range if (weapon==0) { return 0; Modified: gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/FXOpcodes/FXOpc.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -37,6 +37,7 @@ //FIXME: find a way to handle portrait icons better #define PI_CONFUSED 3 +#define PI_BERSERK 4 #define PI_POISONED 6 #define PI_HELD 13 #define PI_SLEEP 14 @@ -52,6 +53,8 @@ #define PI_HOLY 59 #define PI_BOUNCE 65 #define PI_BOUNCE2 67 + +#define PI_BLOODRAGE 76 //iwd2 #define PI_MAZE 78 #define PI_PRISON 79 #define PI_SEQUENCER 92 @@ -193,7 +196,7 @@ int fx_reveal_area (Actor* Owner, Actor* target, Effect* fx);//75 int fx_reveal_creatures (Actor* Owner, Actor* target, Effect* fx);//76 int fx_mirror_image (Actor* Owner, Actor* target, Effect* fx);//77 -//78 protection from weapons is a generic effect +int fx_immune_to_weapon (Actor* Owner, Actor* target, Effect* fx);//78 int fx_visual_animation_effect (Actor* Owner, Actor* target, Effect* fx);//79 unknown int fx_create_inventory_item (Actor* Owner, Actor* target, Effect* fx);//7a int fx_remove_inventory_item (Actor* Owner, Actor* target, Effect* fx);//7b @@ -615,7 +618,6 @@ { "Protection:Animation", fx_generic_effect, -1 }, { "Protection:Backstab", fx_no_backstab_modifier, -1 }, { "Protection:Creature", fx_generic_effect, -1 }, - { "Protection:Weapons", fx_generic_effect, -1 }, { "Protection:Opcode", fx_generic_effect, -1 }, { "Protection:Opcode2", fx_generic_effect, -1 }, { "Protection:Projectile",fx_protection_from_projectile, -1}, @@ -630,6 +632,7 @@ { "Protection:String", fx_generic_effect, -1 }, { "Protection:Tracking", fx_protection_from_tracking, -1 }, { "Protection:Turn", fx_protection_from_turn, -1}, + { "Protection:Weapons", fx_immune_to_weapon, -1}, { "PuppetMarker", fx_puppet_marker, -1}, { "ProjectImage", fx_puppet_master, -1}, { "RetreatFrom", fx_retreat_from, -1 }, @@ -882,14 +885,50 @@ } else { STATE_SET( STATE_BERSERK ); } + + switch(fx->Parameter2) { + case 1: //always berserk + target->SetSpellState(SS_BERSERK); + default: + target->AddPortraitIcon(PI_BERSERK); + break; + case 2: //blood rage + target->SetSpellState(SS_BERSERK); + //immunity to effects: + //5 charm + //0x11 heal + //0x18 panic + //0x27 sleep + //0x2d stun + //0x6d hold + //0x80 confusion + //400 hopelessness + // + target->SetSpellState(SS_BLOODRAGE); + target->SetSpellState(SS_NOHPINFO); + target->SetColorMod(0xff, RGBModifier::ADD, 15, 128, 0, 0); + target->AddPortraitIcon(PI_BLOODRAGE); + break; + } return FX_PERMANENT; } // 0x05 State:Charmed -// 0xf1 ControlCreature +// 0xf1 ControlCreature (iwd2) int fx_set_charmed_state (Actor* Owner, Actor* target, Effect* fx) { if (0) printf( "fx_set_charmed_state (%2d): General: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //blood rage berserking gives immunity to charm (in iwd2) + if (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + + //protection from evil gives immunity to charm (in iwd2) + if (target->HasSpellState(SS_PROTFROMEVIL)) { + return FX_NOT_APPLIED; + } + if (fx->Parameter1 && (STAT_GET(IE_GENERAL)!=fx->Parameter1)) { return FX_NOT_APPLIED; } @@ -1197,6 +1236,10 @@ { if (0) printf( "fx_current_hp_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) { //BASE_MOD( IE_HITPOINTS ); target->NewBase( IE_HITPOINTS, fx->Parameter1, fx->Parameter2&0xffff); @@ -1353,6 +1396,11 @@ 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 (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + if (fx->TimingMode==FX_DURATION_INSTANT_PERMANENT) { BASE_STATE_SET( STATE_PANIC ); } else { @@ -1559,6 +1607,11 @@ 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 (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + target->SetStance(IE_ANI_SLEEP); if (fx->Parameter2) { BASE_STATE_SET( STATE_HELPLESS | STATE_SLEEP ); //don't awaken on damage @@ -1580,6 +1633,11 @@ int fx_set_slowed_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_slowed_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //iwd2 free action or aegis disables this effect + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + if (STATE_GET(STATE_HASTED) ) { BASE_STATE_CURE( STATE_HASTED ); target->fxqueue.RemoveAllEffects( fx_set_haste_state_ref ); @@ -1626,7 +1684,7 @@ if (fx->Parameter2==0x200) { unsigned int j = fx->Parameter1-1; if (j<MAX_SPELL_LEVEL) { - target->spellbook.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD, j, true); + target->spellbook.SetMemorizableSpellsCount(0, IE_SPELL_TYPE_WIZARD, j, true); } } @@ -1686,6 +1744,11 @@ int fx_set_stun_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_stun_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + if (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + if (fx->Parameter2==2) { return power_word_stun_iwd2(target, fx); } @@ -1755,7 +1818,7 @@ { if (0) printf( "fx_brief_rgb (%2d): RGB: %d, Location and speed: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); - int speed = (fx->Parameter2 >> 16) & 0xFF; + int speed = (fx->Parameter2 >> 16) & 0xff; target->SetColorMod(0xff, RGBModifier::ADD, speed, fx->Parameter1 >> 8, fx->Parameter1 >> 16, fx->Parameter1 >> 24, 0); @@ -2781,8 +2844,71 @@ //execute the translated effect return fx_mirror_image_modifier(Owner, target, fx); } -// 0x78 Protection:Weapons (generic effect) +// 0x78 Protection:Weapons +int fx_immune_to_weapon (Actor* /*Owner*/, Actor* /*target*/, Effect* fx) +{ + if (0) printf( "fx_immune_to_weapon (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (!fx->FirstApply) return FX_APPLIED; + + int level; + ieDword mask, value; + + level = -1; + mask = 0; + value = 0; + switch(fx->Parameter2) { + case 0: //enchantment level + level = fx->Parameter1; + break; + case 1: //all magical weapons + mask = IE_INV_ITEM_MAGICAL; + //fallthrough + case 2: //all nonmagical weapons + value = IE_INV_ITEM_MAGICAL; + break; + case 3: //all silver weapons + mask = IE_INV_ITEM_SILVER; + //fallthrough + case 4: //all non silver weapons + value = IE_INV_ITEM_SILVER; + break; + case 5: + value = IE_INV_ITEM_SILVER; + level = 0; + break; + case 6: //all twohanded + mask = IE_INV_ITEM_TWOHANDED; + //fallthrough + case 7: //all not twohanded + value = IE_INV_ITEM_TWOHANDED; + break; + case 8: //all twohanded + mask = IE_INV_ITEM_CURSED; + //fallthrough + case 9: //all not twohanded + value = IE_INV_ITEM_CURSED; + break; + case 10: //all twohanded + mask = IE_INV_ITEM_COLDIRON; + //fallthrough + case 11: //all not twohanded + value = IE_INV_ITEM_COLDIRON; + break; + case 12: + mask = fx->Parameter1; + case 13: + value = fx->Parameter1; + break; + default:; + } + + fx->Parameter1 = (ieDword) level; //putting the corrected value back + fx->Parameter3 = mask; + fx->Parameter4 = value; + return FX_APPLIED; +} + // 0x79 VisualAnimationEffect (unknown) int fx_visual_animation_effect (Actor* /*Owner*/, Actor* /*target*/, Effect* fx) { @@ -2873,7 +2999,14 @@ // 0xb0 MovementRateModifier2 int fx_movement_modifier (Actor* /*Owner*/, Actor* target, Effect* fx) { - if (0) printf( "fx_slow_factor (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + if (0) printf( "fx_movement_modifier (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //iwd2 freeaction disables only 0xb0, who cares + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + //iwd2 aegis doesn't protect against grease/acid fog slowness, but that is + //definitely a bug + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + STAT_MOD(IE_MOVEMENTRATE); return FX_APPLIED; } @@ -2917,6 +3050,11 @@ int fx_set_confused_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_confused_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + if (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + if (fx->TimingMode==FX_DURATION_INSTANT_LIMITED) { BASE_STATE_SET( STATE_CONFUSED ); } else { @@ -3351,6 +3489,11 @@ int fx_set_entangle_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_entangle_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //iwd2 effects that disable entangle + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + if (!fx->Parameter2) { fx->Parameter2=1; } @@ -3380,6 +3523,11 @@ int fx_set_web_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_web_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //iwd2 effects that disable web + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + target->SetSpellState(SS_WEB); //attack penalty in IWD2 STAT_SET_PCF( IE_WEB, 1); @@ -3391,10 +3539,15 @@ int fx_set_grease_state (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_set_grease_state (%2d): Mod: %d, Type: %d\n", fx->Opcode, fx->Parameter1, fx->Parameter2 ); + + //iwd2 effects that disable grease + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + target->SetSpellState(SS_GREASE); STAT_SET_PCF( IE_GREASE, 1); //apparently the movement rate is set by separate opcodes in all engines - //STAT_SET(IE_MOVEMENTRATE, 3); //iwd2 doesn't have this? + //STAT_SET(IE_MOVEMENTRATE, 3); //iwd2 doesn't have this either return FX_APPLIED; } @@ -3580,6 +3733,7 @@ if ( STATE_GET(STATE_DEAD) ) { return FX_NOT_APPLIED; } + if (!EffectQueue::match_ids( target, fx->Parameter1, fx->Parameter2) ) { //if the ids don't match, the effect doesn't stick return FX_NOT_APPLIED; @@ -3599,6 +3753,11 @@ return FX_NOT_APPLIED; } + //iwd2 free action or blood rage disables this effect + if (target->HasSpellState(SS_FREEACTION)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_BLOODRAGE)) return FX_NOT_APPLIED; + if (target->HasSpellState(SS_AEGIS)) return FX_NOT_APPLIED; + if (!EffectQueue::match_ids( target, fx->Parameter1, fx->Parameter2) ) { //if the ids don't match, the effect doesn't stick return FX_NOT_APPLIED; @@ -3699,6 +3858,8 @@ case 1: STAT_SET( IE_CASTINGLEVELBONUSCLERIC, fx->Parameter1 ); break; + default: + return FX_NOT_APPLIED; } return FX_APPLIED; } Modified: gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp =================================================================== --- gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp 2007-10-02 22:20:03 UTC (rev 4803) +++ gemrb/trunk/gemrb/plugins/IWDOpcodes/IWDOpc.cpp 2007-10-22 19:45:58 UTC (rev 4804) @@ -1323,7 +1323,7 @@ for (int i=0;i<6;i++) { core->SummonCreature(real==i?pomab_resref[0]:pomab_resref[1], fx->Resource2, Owner, - target, pomab_positions[i], -1, 100); + target, pomab_positions[i], -1, 100); } return FX_NOT_APPLIED; } @@ -2039,6 +2039,11 @@ int fx_hopelessness (Actor* /*Owner*/, Actor* target, Effect* fx) { if (0) printf( "fx_hopelessness (%2d)\n", fx->Opcode); + + if (target->HasSpellState(SS_BLOODRAGE)) { + return FX_NOT_APPLIED; + } + if (target->SetSpellState( SS_HOPELESSNESS)) return FX_NOT_APPLIED; target->AddPortraitIcon(PI_HOPELESSNESS); STATE_SET(STATE_HELPLESS); @@ -2390,12 +2395,12 @@ if (target->SetSpellState( SS_FREEACTION)) return FX_APPLIED; // immunity to the following effects: - // 0x9a Overlay:Entangle, - // 0x9d Overlay:Web - // 0x9e Overlay:Grease - // 0x6d State:Hold3 - // 0x28 State:Slowed - // 0xb0 MovementRateModifier2 + // 0x9a Overlay:Entangle, ok + // 0x9d Overlay:Web ok + // 0x9e Overlay:Grease ok + // 0x6d State:Hold3 ok + // 0x28 State:Slowed ok + // 0xb0 MovementRateModifier2 ok if (enhanced_effects) { target->AddPortraitIcon(PI_FREEACTION); target->SetColorMod(0xff, RGBModifier::ADD, 30, 0x80, 0x60, 0x60); @@ -2483,7 +2488,17 @@ //426 Aegis int fx_aegis (Actor* /*Owner*/, Actor* target, Effect* fx) { + ieDword tmp; + if (0) printf( "fx_aegis (%2d)\n", fx->Opcode); + //gives immunity against: + //0xda stoneskin + //0x9a entangle + //0x9e grease + //0x9d web + //0x6d hold + //0x28 slow + if (target->SetSpellState( SS_AEGIS)) return FX_APPLIED; //deflection AC bonus // @@ -2506,11 +2521,20 @@ STAT_ADD(IE_SAVEWILL, 2); STAT_ADD(IE_SAVEREFLEX, 2); + if (fx->FirstApply) { + fx->Parameter1=8; + } + tmp = STAT_GET(IE_STONESKINS); + if (fx->Parameter1>tmp) { + STAT_SET(IE_STONESKINS, fx->Parameter1); + } + if (enhanced_effects) { target->AddPortraitIcon(PI_AEGIS); target->SetColorMod(0xff, RGBModifier::ADD, 30, 0x80, 0x60, 0x60); target->SetGradient(14); } + return FX_APPLIED; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |