SphereCommunity
Problem with custom spells... - Printable Version

+- SphereCommunity (https://forum.spherecommunity.net)
+-- Forum: Sphere 0.56d (/Forum-Sphere-0-56d)
+--- Forum: Script Help (/Forum-Script-Help)
+--- Thread: Problem with custom spells... (/Thread-Problem-with-custom-spells)

Pages: 1 2


RE: Problem with custom spells... - admin phoenix - 05-04-2012 08:56 PM

this code has to be in the file sphere_backward_compatibility.scp
cause there is also an function called npccast that doesn´t work.
thanks for this one!


RE: Problem with custom spells... - Anarch Cassius - 05-05-2012 06:18 AM

Here's one with a few changes:
Better comments
Returns 0 if the spell can't be cast
RUNES function commented out but explained and included

EDIT: I have a 3rd function I use to determine if the spell is in skill range. I use this outside NPCCAST beforehand in the AI to see if it's even an option before it runs the mana test and sets the spell.

For now I put it in the main function. You can remove this part if you want to use NPCCANCAST like I do. The mana check should always stay in NPCCAST; the game will fizzle an NPC that tries to cast above skill and although it deducts mana it doesn't actually ensure there is enough allowing them cast at 0 mana without it.

A simple example of using CANCAST in AI:
Code:
[FUNCTION npccast_sorcery_offense]
    IF (<I.UID> == <OBJ.UID>)
        return 0
    ENDIF
    IF  (<npccancast s_summon_chaos_daemon>) && !(<R4>) && !(<FLAGS>&statf_conjured)
        npccast s_summon_chaos_daemon,<obj>
        return 1
    ELIF (<npccancast s_detonation>) && (<attacker> > 1) && !(<R3>)
        npccast s_detonation,<obj>
        return 1
    ELIF (<npccancast s_summon_djinn>) && !(<R3>) && !(<FLAGS>&statf_conjured)
        npccast s_summon_djinn,<obj>
        return 1
    ELIF (<npccancast s_summon_efreet>) && !(<R3>) && !(<FLAGS>&statf_conjured)
        npccast s_summon_efreet,<obj>
        return 1
    ELIF (<npccancast s_summon_hellhound>) && !(<R3>) && !(<FLAGS>&statf_conjured)
        npccast s_summon_hellhound,<obj>
        return 1
    ELIF (<npccancast s_fire_bolt>)
        npccast s_fire_bolt,<obj>
        return 1
    ENDIF
return 0
If goes down this list finding the first spell that isn't too difficult to cast and isn't randomly selected against or innapproriate to the situation. So they favor the most powerful spell the can cast but random selection keeps it interesting.

(Appropriate here means not using AoE against one target and not letting summons cast summons because that's just plain wrong)

I'm still working on the system. I should probably adjust this to look for a new spell if npccast returns 0 (not enough mana) but I don't want to overwhelm people.


The major functions

Code:
[FUNCTION npccast]
// Determine spell and skill used to cast
LOCAL.SPELL = <EVAL <ARGV[0]> &~ 0ff000000>
LOCAL.SKILL = <EVAL (<STREAT <SERV.SPELL.<LOCAL.SPELL>.SKILLREQ>>) &~ 0ff000000>
IF (<SERV.SPELL.<LOCAL.SPELL>.MANAUSE> > <MANA>)
    RETURN 0
ENDIF

//You can remove this if you use NPCCANCAST to check first
IF (<FVAL <STRARG <SERV.SPELL.<LOCAL.SPELL>.SKILLREQ>>+50> > <I.<SERV.SKILL.<LOCAL.SKILL>.KEY>>)
    RETURN 0
ENDIF

//Uncomment the following lines if you want NPCs to say WoP, you'll need the RUNES function
//IF (<EVAL STRLEN(<SERV.SPELL(<LOCAL.SPELL>).RUNES>)> > 0)
//     SAY <RUNES <LOCAL.SPELL>>
//ENDIF

//If we didn't get a valid skill, default to Magery
IF !(<LOCAL.SKILL>)
  LOCAL.SKILL = 25
ENDIF
// This is part of my casting management, you may also find it useful in systems
TAG.LASTCASTING=<eval (<SERV.TIME>+<SERV.SPELL.<LOCAL.SPELL>.CAST_TIME>)>
TAG.SPELLCASTING=<LOCAL.SPELL>

// Set spell target
IF (<ARGV> > 2) //use coords if given
    ACT = 0
    ACTP = <ARGV[1]>, <ARGV[2]>, <ARGV[3]>, <ARGV[4]>
ELIF (<SERV.SPELL.<LOCAL.SPELL>.FLAGS> & spellflag_targ_xyz) //use coords for ground targ spells regardless
    ACTP = <ACT.P>
    ACT = 0
ELSE
    REF1 = <ARGV[1]>
    IF !(<REF1.UID>)
        REF1 = <ACT.UID>
        IF !(<REF1.UID>)
            REF1 = <UID>
        ENDIF
    ENDIF
    ACT = <REF1.UID>
    ACTP = <REF1.P>
ENDIF

    
// Set character action
ACTPRV = <UID>
ACTARG1 = <LOCAL.SPELL>
ACTION = <LOCAL.SKILL>
RETURN 1

This function returns the WoP for a given spell. I use this in my custom spellbooks and for NPC casting.

Code:
[Function RUNES]
LOCAL.LENGTH = <EVAL STRLEN(<SERV.SPELL(<args>).RUNES>)>
LOCAL.CURRUNE=0
local.RUNESTRING="0"
WHILE (<eval <LOCAL.CURRUNE>> <= <eval <LOCAL.LENGTH>>)
    IF (strmatch(*0*,<LOCAL.runestring>))
    IF (strmatch(A,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="An "
    ELSEIF (strmatch(B,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Bet "
    ELSEIF (strmatch(C,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Corp "
    ELSEIF (strmatch(D,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Des "
    ELSEIF (strmatch(E,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Ex "
    ELSEIF (strmatch(F,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Flam "
    ELSEIF (strmatch(G,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Grav "
    ELSEIF (strmatch(H,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Hur "
    ELSEIF (strmatch(I,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="In "
    ELSEIF (strmatch(J,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Jux "
    ELSEIF (strmatch(K,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Kal "
    ELSEIF (strmatch(L,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Lor "
    ELSEIF (strmatch(M,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Mani "
    ELSEIF (strmatch(N,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Nox "
    ELSEIF (strmatch(O,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Ort "
    ELSEIF (strmatch(P,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Por "
    ELSEIF (strmatch(Q,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Quas "
    ELSEIF (strmatch(R,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Rel "
    ELSEIF (strmatch(S,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Sanct "
    ELSEIF (strmatch(T,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Tym "
    ELSEIF (strmatch(U,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Uus "
    ELSEIF (strmatch(V,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Vas "
    ELSEIF (strmatch(W,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Wis "
    ELSEIF (strmatch(X,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Xen "
    ELSEIF (strmatch(Y,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Ylem "
    ELSEIF (strmatch(Z,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="Zu "
    ENDIF
    ELSE
    IF (strmatch(A,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>An "
    ELSEIF (strmatch(B,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Bet "
    ELSEIF (strmatch(C,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Corp "
    ELSEIF (strmatch(D,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Des "
    ELSEIF (strmatch(E,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Ex "
    ELSEIF (strmatch(F,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Flam "
    ELSEIF (strmatch(G,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Grav "
    ELSEIF (strmatch(H,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Hur "
    ELSEIF (strmatch(I,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>In "
    ELSEIF (strmatch(J,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Jux "
    ELSEIF (strmatch(K,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Kal "
    ELSEIF (strmatch(L,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Lor "
    ELSEIF (strmatch(M,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Mani "
    ELSEIF (strmatch(N,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Nox "
    ELSEIF (strmatch(O,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Ort "
    ELSEIF (strmatch(P,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Por "
    ELSEIF (strmatch(Q,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Quas "
    ELSEIF (strmatch(R,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Rel "
    ELSEIF (strmatch(S,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Sanct "
    ELSEIF (strmatch(T,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Tym "
    ELSEIF (strmatch(U,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Uus "
    ELSEIF (strmatch(V,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Vas "
    ELSEIF (strmatch(W,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Wis "
    ELSEIF (strmatch(X,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Xen "
    ELSEIF (strmatch(Y,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Ylem "
    ELSEIF (strmatch(Z,<STRSUB <eval <LOCAL.CURRUNE>> 1 <SERV.SPELL(<args>).RUNES>>))
        local.RUNESTRING="<local.RUNESTRING>Zu "
    ENDIF
    ENDIF
    LOCAL.CURRUNE += 1
ENDWHILE
RETURN <local.RUNESTRING>

Code:
[FUNCTION npccancast]
LOCAL.SPELL = <EVAL <args>>
LOCAL.SKILL = <EVAL (<STREAT <SERV.SPELL.<LOCAL.SPELL>.SKILLREQ>>)>
IF !(<SERV.SPELL.<LOCAL.SPELL>.MANAUSE> > <MANA>) && !(<FVAL <STRARG <SERV.SPELL.<LOCAL.SPELL>.SKILLREQ>>+50> > <I.<SERV.SKILL.<LOCAL.SKILL>.KEY>>)
    RETURN 1
ELSE
    RETURN 0
ENDIF



RE: Problem with custom spells... - Jonaleth - 05-13-2012 12:44 AM

Thank you for all of your comments, that was very kind of you.
I will study your scripts and try to learn from them. Smile


RE: Problem with custom spells... - admin phoenix - 05-14-2012 04:15 PM

and use the force Smile