Help - Search - Members - Calendar
Full Version: Protagonist Spell Only
The Black Wyrm's Lair - Forums > Mod development resources & discussion > Modder's Workshop
Rabain
I want to create a spell that only the protagonist can cast. If anyone else tries to cast it they will get a message.

So far I have tried casting a spell that sets a global. In a script if have the following:

CODE
IF
    Global("PConly","GLOBAL",1)
    Class(Player1,MAGE_ALL)
    IsActive(Player1)
THEN
    RESPONSE #100
        ActionOverride(Player1,ForceSpellRES("MyPConlyspell",Myself))         ActionOverride(Player1,DisplayStringHead(Myself,8538))
        SetGlobal("PConly","GLOBAL",2)
END


Ignore the DisplayStringHead..thats just for testing.

What is happening is that even if someone else in the party casts the first spell my Player1 starts casting "MyPConlySpell"

I can't seem to find a valid script command that specifies PC only.

I will also need a command that will work if someone not the PC casts the spell. I can use this in a second script block.
Sikret
If I understood you correctly, what you have done so far is this:

1- You have a spell (say, spell1) which if cast by anyone will set the global variable PCOnly to 1.

2- Then you have written a script to make sure that if the global is set to one and if it is set to 1 because player 1 (and noone else) has cast spell1, then your player one will also cast spell2 on himself. (spell2 = MyPCOnlyspell)

Right?

If so, then it is natural that it has not worked. The way to solve the problem is easy:

Spell1 doesn't need to set any variable. It doesn't need to do anything at all. Just Extend Baldur.bcs and Baldur25.bcs so that whenever Player1 casts spell1, the spell2 is applied to him while whenever any other charcter casts spell1 the message you want be displayed (The only additional work here is that you need to add spell1 to spell.ids)

CODE
  

IF
    Class(Player1,MAGE_ALL)
    SpellCast(Player1,Spell1) // You need to have spell1 in your spell.ids
    RESPONSE #100
        ActionOverride(Player1,ReallyForceSpellRES("MyPConlyspell",Myself))  //

END



IF
    SpellCast(Player2,Spell1)
    RESPONSE #100
        ActionOverride(Player2,DisplayeString(Myself,~Only the protagonist can cast this spell~)) //

END

IF
    SpellCast(Player3,Spell1)
    RESPONSE #100
        ActionOverride(Player2,DisplayeString(Myself,~Only the protagonist can cast this spell~)) //

END

IF
    SpellCast(Player4,Spell1)
    RESPONSE #100
        ActionOverride(Player2,DisplayeString(Myself,~Only the protagonist can cast this spell~)) //

END

IF
    SpellCast(Player5,Spell1)
    RESPONSE #100
        ActionOverride(Player2,DisplayeString(Myself,~Only the protagonist can cast this spell~)) //

END

IF
    SpellCast(Player6,Spell1)
    RESPONSE #100
        ActionOverride(Player2,DisplayeString(Myself,~Only the protagonist can cast this spell~)) //

END



Also, If the spell's (spell2's) effects do not depend on the caster's level of experience, you can use ApplySpellRES (instead of ReallyForceSpellRES)

Rabain
Thanks, goods stuff. I'll probably keep the variable as the spell is a one-time casting, no second chances.

ReallyForcSpellRes() has a 0 casting time I think so I might stick with ForceSpellRes().

Also I think I can shorten the other blocks into one using OR(5) and DisplayStringNoName(O:Object*,I:StrRef*) as it doesn't matter who has tried to cast the spell only that the player gets the message.

Thanks, I've been looking at Triggers, Objects etc all day and my head has been a bit wrecked by all of it!
Sikret
You are welcome.

With ForceSpellRES you will have the spell casting animations two times: Once for spell1 (which does nothing) and once for Spell2 (if you set the casting time of spell1 to zero, you will not have casting animation for it but you will still read the message of a spell being cast once for spell1 and once for spell2). So, I recommend to set the casting time of the spell for spell1 and use ApplyspellRes for spell2 if its effects don't depend on the caster's level of experience. (One of the differences between ApplySpell and ReallyForceSpell which is not known to many is that ApplySpell doesn't respect the caster's level of experience and always applies the spell with the minimum duration and damage amount as if it is cast by a first level caster; the other differences which are relevant in this case are that with ApplyspellRES you will not see any casting animation, any casting finishing sound and any message on the screen saying that a spell is cast).
Rabain
Something isn't working here. The first spell is in spell.ids and the global is being set to 1 however the ActionOverride is not happening. I can only assume either Class() or SpellCast() is not returning true (the game is putting in LONG_BOW itself as this and MAGE_ALL have the same value in class.ids).
This block is in baldur.bcs.
CODE
IF
    Global("WTPFAMA1","GLOBAL",1)
    Class(Player1,LONG_BOW)
    SpellCast(Player1,MY_SPELL)
THEN
    RESPONSE #100
        ActionOverride(Player1,ApplySpellRES("WTPFAMA1",Myself))
        SetGlobal("WTPFAMA1","GLOBAL",2)
END


I have tried replacing ApplySpellRES() with ForceSpell() and ReallyForceSpell() but that doesn't work either. I've also tried sticking in a DisplayStringHead() to see if it's just the ActionOverride() but no string appeared.

Any idea's?
Sikret
spell1 sets the global to one in the same round that script needs it to be 1. So when checking the trigger the global is not 1 yet. You can divide the script to two distinct blocks for player 1. In the first one if player 1 has cast the spell the global will be set to one. In the second block, if the global is set to one, spell2 will be apllied to player 1. Still, spell1 should do nothing. The global will be set in the script (first block) only if spell1 is cast by player1.

CODE
  

IF
    Global("WTPFAMA1","GLOBAL",0)
    Class(Player1,LONG_BOW)
    SpellCast(Player1,MY_SPELL)
THEN
    RESPONSE #100
        SetGlobal("WTPFAMA1","GLOBAL",1)
END

IF
    Global("WTPFAMA1","GLOBAL",1)
THEN
    RESPONSE #100
        SetGlobal("WTPFAMA1","GLOBAL",2)
        ActionOverride(Player1,ApplySpellRES("WTPFAMA1",Myself))
END



Sikret
And there is one other possibility why the global had been not set to 1 when casting spell1 (in the previous method you had used). How had you made spell1 to set the variable? Had you added the ModifyGlobal effect to the spell's extended effects or to its casting features?
Rabain
I have 2 problems now...not too big thanks to your recommendations:

1. If I don't include the global in MY_SPELL nothing happens when Player1 casts MY_SPELL which is strange considering the script block I used from your post above should set it to 1 if it is 0.

2. If I do use the global (extended effect) in MY_SPELL then it works fine for Player1...however if any of the other Players(2-6) cast MY_SPELL then nothing happens for them (they don't get spell WTPFAMA1 cast) except the global in MY_SPELL is set to 2! This is even stranger because the only place the global gets set to 2 is in the block above when the ActionOverride applies spell WTPFAMA1 to Player1 (and that doesn't happen if Player2-6 casts it!). Also the message "Only the protagonist may cast this spell" doesn't get shown even though Player2-6 has cast MY_SPELL.

Problem 2 does have a workaround as the result of casting the second spell WTPFAMA1 involves further globals being set so I could possibly include an extra block to set the original global back to 0 if none of the other globals get set to 1 as they won't be if anyone other than Player1 casts MY_SPELL.
Sikret
QUOTE(Rabain @ Mar 9 2007, 03:25 PM) *
I have 2 problems now...not too big thanks to your recommendations:

1. If I don't include the global in MY_SPELL nothing happens when Player1 casts MY_SPELL which is strange considering the script block I used from your post above should set it to 1 if it is 0.


Check MY_SPELL's file to make sure that it is a wizard spell (not an innate spell). If you want it to be an innate spell, then you will need to replace the SpellCast(Player1,MY_SPELL) trigger with SpellCastInnate(Player1,MY_SPELL). The spell should not set the global variable. The variable should be set via script as mentioned before.

Rabain
This still isn't working.

Okay this is where i am: I've edited SPWI123 and removed the effects so that it doesn't call anything, no Effect opcodes/no global but I haven't changed anything else. This is in spell.ids already...no changes needed there.

When my mage casts the spell nothing happens (global doesn't change from 0)even though this is the block in baldur.bcs:

CODE
IF
    Global("WTPFAMA1","GLOBAL",0)
    Class(Player1,LONG_BOW)
    SpellCast(Player1,WIZARD_FIND_FAMILAR)
THEN
    RESPONSE #100
        SetGlobal("WTPFAMA1","GLOBAL",1)
END

IF
    Global("WTPFAMA1","GLOBAL",1)
THEN
    RESPONSE #100
        SetGlobal("WTPFAMA1","GLOBAL",2)
        ActionOverride(Player1,ApplySpellRES("WTPFAMA1",Myself)) END


If I edit SPWI123 and add the modify global effect then Player1 can cast the spell and gets WTPFAMA1 cast on them. If any other party member casts SPWI123 then the spell casts but they don't get WTPFAMA1 cast on them or player1 (though global is set to 2).

This still doesn't make sense to me.

I did another test just now and removed block 1 completely from baldur.bcs and it behaves the same, spell cast on player1, no spell if any other party member casts SPWI123 (though global is set to 2). It does not work at all if I remove the global effect from the spell SPWI123.

pro5
Rabain, the following works for me:

CODE
IF
    SpellCast(Player1,WIZARD_PROTECTION_FROM_EVIL)
    Class(Player1,MAGE_ALL)
THEN
    RESPONSE #100
        ActionOverride(Player1,ApplySpellRES("P5#TEST",Myself))
END

IF
    SpellCast([ANYONE],WIZARD_PROTECTION_FROM_EVIL)
    !SpellCast(Player1,WIZARD_PROTECTION_FROM_EVIL)
THEN
    RESPONSE #100
        DisplayStringNoName(Player1,8538)
END
Sikret
Perhaps it's soemthing hardcoded related to Find Familiar spell's unknown effects (did you also omit its casting features?). Pick another more routine spell and modify its effects and test it. The way I suggested should work fine.
Rabain
Yeah its weird, I've tried other spells Stoneskin and MirrorImage as the trigger and it works fine.

If I try to use Find Familiar it doesn't work.

Edit: If i try to modify any spell and add a new entry in spell.ids it doesn't work! For example I renamed Stoneskin to SPWI450.spl (which doesn't exist) and added a new entry to spell.ids "2450 WTP_FAMILIAR", changed the baldur.bcs to use WTP_FAMILIAR instead of WIZARD_STONESKIN...result = nothing happens!
pro5
Did you also change the memorized spell reference on your mage(s) to SPWI450?
Rabain
Yep and I know that works because i removed the Stoneskin effect from the spell before saving.

I've even updated the Scroll itm to reference the new spell number!

With all the effort going on this I think it might be easier to implement some kind of mini-quest and give the new spell as an innate to Player1 and simply remove all other references in stores etc.

Just for info purposes this is an upgrade to the standard Find Familiar for WTP which includes getting a choice of which Familiar you want as well as a new Familiar to bring the number up to 9 (one for each alignment).
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2024 Invision Power Services, Inc.