summaryrefslogtreecommitdiff
path: root/world
diff options
context:
space:
mode:
authormekolat <mekolat@users.noreply.github.com>2015-06-11 11:13:11 -0400
committermekolat <mekolat@users.noreply.github.com>2016-03-30 11:22:47 -0400
commitbc4deaf81d9701261baac6a10d762b0f40e7f65f (patch)
treee539e3a49756626e27d4491fccb7a6862b12a120 /world
parent9e7f46ac732851c1359a15837c82ebf67ea2be39 (diff)
downloadserverdata-bc4deaf81d9701261baac6a10d762b0f40e7f65f.tar.gz
serverdata-bc4deaf81d9701261baac6a10d762b0f40e7f65f.tar.bz2
serverdata-bc4deaf81d9701261baac6a10d762b0f40e7f65f.tar.xz
serverdata-bc4deaf81d9701261baac6a10d762b0f40e7f65f.zip
initial commit for magic v3
Fix Druid Tree and add hug to TMW
Diffstat (limited to 'world')
-rw-r--r--world/map/.gitignore1
-rw-r--r--world/map/conf/magic-level0.sex39
-rw-r--r--world/map/conf/magic-level1.sex494
-rw-r--r--world/map/conf/magic-level2.sex1462
-rw-r--r--world/map/conf/magic-level3.sex179
-rw-r--r--world/map/conf/magic-level4.sex3
-rw-r--r--world/map/conf/magic-level5.sex55
-rw-r--r--world/map/conf/magic-misc.sex112
-rw-r--r--world/map/conf/magic-procedures.sex7
-rw-r--r--world/map/conf/magic-quests.sex154
-rw-r--r--world/map/conf/tmwa-map.conf17
-rw-r--r--world/map/db/const-magic.txt62
-rw-r--r--world/map/db/const.txt69
-rw-r--r--world/map/db/params.txt51
-rw-r--r--world/map/npc/001-1/ched.txt4
-rw-r--r--world/map/npc/001-1/children.txt2
-rw-r--r--world/map/npc/001-1/guards.txt2
-rw-r--r--world/map/npc/001-2/government_building.txt8
-rw-r--r--world/map/npc/001-2/pauline.txt10
-rw-r--r--world/map/npc/001-2/tondar.txt2
-rw-r--r--world/map/npc/001-2/wizards.txt99
-rw-r--r--world/map/npc/002-1/elanore.txt14
-rw-r--r--world/map/npc/006-1/spirit.txt4
-rw-r--r--world/map/npc/006-1/tree.txt6
-rw-r--r--world/map/npc/007-2/witch.txt8
-rw-r--r--world/map/npc/008-1/hinnak.txt2
-rw-r--r--world/map/npc/009-2/misc.txt2
-rw-r--r--world/map/npc/009-2/wyara.txt6
-rw-r--r--world/map/npc/009-3/sword.txt4
-rw-r--r--world/map/npc/009-6/brodomir.txt2
-rw-r--r--world/map/npc/009-7/eventHandler.txt2
-rw-r--r--world/map/npc/009-7/rouge.txt4
-rw-r--r--world/map/npc/011-1/auldsbel.txt20
-rw-r--r--world/map/npc/012-3/mana-seed.txt2
-rw-r--r--world/map/npc/013-1/sagatha.txt14
-rw-r--r--world/map/npc/013-2/wizard.txt2
-rw-r--r--world/map/npc/014-1/wedding-officiator.txt12
-rw-r--r--world/map/npc/015-1/sword.txt6
-rw-r--r--world/map/npc/017-4/waric.txt12
-rw-r--r--world/map/npc/017-9/npcs.txt10
-rw-r--r--world/map/npc/027-6/general_krukan.txt4
-rw-r--r--world/map/npc/027-7/general_razha.txt4
-rw-r--r--world/map/npc/027-8/general_terogan.txt4
-rw-r--r--world/map/npc/029-1/barrier.txt2
-rw-r--r--world/map/npc/029-2/morgan.txt8
-rw-r--r--world/map/npc/029-2/tanisha.txt2
-rw-r--r--world/map/npc/029-3/parua.txt6
-rw-r--r--world/map/npc/030-4/mana_battery.txt6
-rw-r--r--world/map/npc/031-4/cindyCave.txt4
-rw-r--r--world/map/npc/033-1/kimarr.txt2
-rw-r--r--world/map/npc/051-3/ambush.txt4
-rw-r--r--world/map/npc/051-3/reinforcements.txt4
-rw-r--r--world/map/npc/052-1/channelling.txt10
-rw-r--r--world/map/npc/052-2/lobby.txt2
-rw-r--r--world/map/npc/052-2/partyroom.txt8
-rw-r--r--world/map/npc/052-2/storage.txt10
-rw-r--r--world/map/npc/commands/_atcommand_local.txt.example12
-rw-r--r--world/map/npc/commands/_import.txt4
-rw-r--r--world/map/npc/commands/_procedures.txt53
-rw-r--r--world/map/npc/commands/marry.txt69
-rw-r--r--world/map/npc/commands/zeny.txt77
-rw-r--r--world/map/npc/doc/magic23
-rwxr-xr-xworld/map/npc/functions/debug.txt40
-rw-r--r--world/map/npc/functions/global_event_handler.txt1
-rw-r--r--world/map/npc/functions/hug.txt24
-rw-r--r--world/map/npc/functions/strangerquiz.txt2
-rw-r--r--world/map/npc/functions/superdebug.txt16
-rw-r--r--world/map/npc/items/check_wand.txt65
-rw-r--r--world/map/npc/items/magic_gm_top_hat.txt16
-rw-r--r--world/map/npc/magic/README.md63
-rw-r--r--world/map/npc/magic/_import.txt38
-rw-r--r--world/map/npc/magic/_procedures.txt135
-rw-r--r--world/map/npc/magic/level0-wand.txt74
-rw-r--r--world/map/npc/magic/level1-aggravate.txt22
-rw-r--r--world/map/npc/magic/level1-detect-magic.txt29
-rw-r--r--world/map/npc/magic/level1-experience.txt41
-rw-r--r--world/map/npc/magic/level1-flare-dart.txt33
-rw-r--r--world/map/npc/magic/level1-grow-alizarin.txt37
-rw-r--r--world/map/npc/magic/level1-grow-cobalt.txt37
-rw-r--r--world/map/npc/magic/level1-grow-gamboge.txt37
-rw-r--r--world/map/npc/magic/level1-grow-mauve.txt37
-rw-r--r--world/map/npc/magic/level1-lesser-heal.txt41
-rw-r--r--world/map/npc/magic/level1-magic-blade.txt34
-rw-r--r--world/map/npc/magic/level1-make-sulphur.txt24
-rw-r--r--world/map/npc/magic/level1-summon-maggots.txt52
-rw-r--r--world/map/npc/magic/level1-transmute-wood.txt36
-rw-r--r--world/map/npc/magic/level2-arrow-hail.txt112
-rw-r--r--world/map/npc/magic/level2-barrier.txt48
-rw-r--r--world/map/npc/magic/level2-detect-players.txt32
-rw-r--r--world/map/npc/magic/level2-enchant-lifestone.txt35
-rw-r--r--world/map/npc/magic/level2-flying-backpack.txt39
-rw-r--r--world/map/npc/magic/level2-happy-curse.txt42
-rw-r--r--world/map/npc/magic/level2-hide.txt43
-rw-r--r--world/map/npc/magic/level2-lay-on-hands.txt57
-rw-r--r--world/map/npc/magic/level2-lightning-strike.txt67
-rw-r--r--world/map/npc/magic/level2-magic-knuckles.txt32
-rw-r--r--world/map/npc/magic/level2-make-arrows.txt26
-rw-r--r--world/map/npc/magic/level2-make-iron-powder.txt26
-rw-r--r--world/map/npc/magic/level2-protect.txt48
-rw-r--r--world/map/npc/magic/level2-rain.txt103
-rw-r--r--world/map/npc/magic/level2-shear.txt49
-rw-r--r--world/map/npc/magic/level2-summon-fluffies.txt53
-rw-r--r--world/map/npc/magic/level2-summon-mouboo.txt53
-rw-r--r--world/map/npc/magic/level2-summon-pinkie.txt53
-rw-r--r--world/map/npc/magic/level2-summon-snakes.txt54
-rw-r--r--world/map/npc/magic/level2-summon-spiky-mushroom.txt53
-rw-r--r--world/map/npc/magic/level2-summon-wickedmushroom.txt54
-rw-r--r--world/map/npc/magic/level2-toxic-dart.txt36
-rw-r--r--world/map/npc/magic/level3-necromancy.txt54
-rw-r--r--world/map/npc/scripts.conf7
110 files changed, 2516 insertions, 2876 deletions
diff --git a/world/map/.gitignore b/world/map/.gitignore
index 2c681650..07be4021 100644
--- a/world/map/.gitignore
+++ b/world/map/.gitignore
@@ -5,3 +5,4 @@
/db/const-debugflag.txt
/npc/functions/motd.txt
+/npc/commands/_atcommand_local.txt
diff --git a/world/map/conf/magic-level0.sex b/world/map/conf/magic-level0.sex
deleted file mode 100644
index f376b2cd..00000000
--- a/world/map/conf/magic-level0.sex
+++ /dev/null
@@ -1,39 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 0 spells "
-"--------------------------------------------------------------------------------"
-(SPELL () wand "#confringo" ()
- (LET school MAGIC)
- (=>
- (GUARD
- (CASTTIME 500))
- (EFFECT
- (SCRIPT "{callfunc \"CheckWand\";}")
- (IF (==
- (script_int caster "@Wand")
- 0)
- (ABORT))
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL install_attack_spell
- (+ (script_int caster "@Wand")
- (/ spellpower 10))
- 1200
- 3
- (script_int caster "@WandID"))
- (CALL gain_xp 1 3)
- (ATTRIGGER
- (CALL attack_check target)
- (SCRIPT "{callfunc \"WandMana\";}")
- (IF (==
- (script_int caster "@WandAttack")
- 0)
- (ABORT))
- (SET damage
- (* (script_int caster "@Wand")
- (/ spellpower
- 3)))
- (SET damage_bonus
- (* (script_int caster "@Wand")
- (/ spellpower
- 3)))
- (CALL elt_damage target damage damage_bonus ELT_NEUTRAL ELT_NEUTRAL 5)))))
diff --git a/world/map/conf/magic-level1.sex b/world/map/conf/magic-level1.sex
deleted file mode 100644
index da29ad22..00000000
--- a/world/map/conf/magic-level1.sex
+++ /dev/null
@@ -1,494 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 1 spells "
-"--------------------------------------------------------------------------------"
-(SPELL () ask-magic-exp "#abizit" ()
- (LET level 1)
- (LET school MAGIC)
- (=>
- (GUARD
- (MANA 1)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level)))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (SET level
- (skill caster MAGIC))
- (SET experience
- (&
- (>>
- (script_int caster SCRIPT_XP)
- SCRIPT_XP_SHIFT)
- SCRIPT_XP_MASK))
- (IF (&&
- (== experience SCRIPT_XP_MASK)
- (> level 4))
- (message caster "You are as proficient at magic as you can possibly be.")
- (BLOCK "This duplicates the table in mana-seed.txt"
- (IF (> level 4)
- (SET max_experience SCRIPT_XP_MASK)
- (IF (== level 4)
- (SET max_experience 40000)
- (IF (== level 3)
- (SET max_experience 8000)
- (IF (== level 2)
- (SET max_experience 1200)
- (SET max_experience 100)))))
- (SET ratio
- (/
- (-
- (* 10 experience)
- (random
- (/ max_experience 30)))
- max_experience)) "Randomness: jitter a bit at the transitions to give more precise information if used frequently"
- (IF (>= ratio 45)
- (message caster
- (+ "Magic flows naturally from you, readily and with ease. Your understanding of what you can currently control at present is flawless, far beyond your requirements to cast magic at this level."
- (if_then_else
- (>= level MAX_MAGIC_LEVEL)
- ""
- " Surely the Mana Seed will more than readily offer more magic for such a proficient user.")))
- (IF (>= ratio 20)
- (message caster "You have perfect control of what you understand now, but there is now a distinct sensation of something more, something indescribable. If only the Mana Seed would give more magic to you...")
- (IF (>= ratio 10)
- (message caster
- (+ "You feel in perfect control of your magic"
- (if_then_else
- (>= level MAX_MAGIC_LEVEL)
- "."
- ", and seem on the verge of something more... perhaps you should see the Mana Seed to ask for more magic?")))
- (IF (>= ratio 9)
- (message caster "You feel in almost perfect control of your magic.")
- (IF (>= ratio 8)
- (message caster "You feel that you have very good control of your magic.")
- (IF (>= ratio 7)
- (message caster "You feel quite in control of your magic.")
- (IF (>= ratio 6)
- (message caster "You feel mostly in control of your magic.")
- (IF (>= ratio 5)
- (message caster "You feel somewhat in control of your magic.")
- (IF (>= ratio 4)
- (message caster "You feel you still have a few difficulties in controlling your magic.")
- (IF (>= ratio 3)
- (message caster "Trying to control your magic is still rather troublesome.")
- (IF (>= ratio 2)
- (message caster "You feel that you have only the bare minimum of control over your magic.")
- (IF (>= ratio 1)
- (message caster "You feel quite overwhelmed by your magic, but are beginning to see patterns.")
- (message caster "You feel completely overwhelmed by your magic."))))))))))))))))))
-
-(SPELL () transmute-wood-to-figurine "#parum" (STRING name)
- (LET level 1)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 5)
- (CASTTIME 4000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "RawLog"))
- (|
- (=>
- (REQUIRE
- (== name "boo"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "MoubooFigurine" 1 "WarpedLog" 40)
- (CALL gain_xp 1 0)))
- (=>
- (REQUIRE
- (== name "lurk"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "WarpedLog" 1 "WarpedLog" 40)
- (message caster "You have no idea what a Skytlurk looks like."))))))
-
-(SPELL () make-sulphur "#gole" ()
- (LET level 1)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 4)
- (CASTTIME 4000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "PileOfAsh"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "SulphurPowder"
- (+
- (+ 1
- (/ spellpower 100))
- (/
- (random
- (max 1
- (- 800 spellpower)))
- 180))
- "PileOfAsh"
- 50)
- (CALL gain_xp 1 1))))
-
-(SPELL () lesser-heal "#lum" (STRING target)
- (LET level 1)
- (LET school LIFE)
- (=>
- (GUARD
- (MANA 6)
- (CASTTIME 500)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (if_then_else
- (failed
- (pc target))
- 1
- (<
- (rdistance
- (location caster)
- (location
- (pc target)))
- (+ 2
- (/ spellpower 100)))))
- (GUARD
- (COMPONENTS "Lifestone")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (failed
- (pc target))
- (BLOCK
- (IF (&&
- (||
- (== target "mouboo")
- (== target "Mouboo"))
- (<
- (rdistance
- (location caster)
- (location
- (npc "Mouboo")))
- (+ 2
- (/ spellpower 100))))
- (SCRIPT "{
- mes \"Your spell seems to have no effect on the mouboo.\";
- close;
- }")
- (SET target caster)))
- (BLOCK
- (SET target
- (pc target))
- (IF (is_dead target)
- (ABORT))))
- (CALL gain_heal_xp
- (min 200
- (-
- (max_hp target)
- (hp target)))
- 1
- 2
- 2) "report half values for non-instaheal"
- (CALL heal target 200)
- (IF (>
- (skill caster DARK)
- 1)
- (status_change caster SC_HALT_REGENERATE 0 0 0 0 2000))
- (CALL gain_xp 1 2))))
-
-(SPELL () flare-dart "#flar" ()
- (LET level 1)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 10)
- (CASTTIME 500)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 2))
- (COMPONENTS "SulphurPowder"))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (SET damage
- (* 5
- (sqrt spellpower)))
- (SET damage_bonus
- (+ 5
- (/
- (level caster)
- 3)))
- (CALL install_attack_spell
- (+ 3
- (/ spellpower 50))
- 1200
- 4
- 31)
- (CALL gain_xp 1 3)
- (ATTRIGGER
- (CALL attack_check target)
- (CALL elt_damage target damage damage_bonus ELT_WATER ELT_FIRE 15)))))
-
-(SPELL () magic-blade "#chiza" ()
- (LET level 1)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 9)
- (CASTTIME 500)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level)))
- (|
- (=>
- (COMPONENTS "SharpKnife")
- (EFFECT
- (CALL adjust_spellpower WAR)
- (CALL default_effect)
- (CALL install_melee_spell
- (+ 10
- (/ spellpower 15))
- 1200
- 30)
- (CALL gain_xp 1 4)
- (ATTRIGGER
- (CALL melee_damage target 60
- (+ 5
- (str caster))))))
- (=>
- (COMPONENTS "Knife")
- (EFFECT
- (CALL adjust_spellpower WAR)
- (CALL default_effect)
- (CALL install_melee_spell
- (+ 10
- (/ spellpower 15))
- 1200
- 30)
- (CALL gain_xp 1 5)
- (ATTRIGGER
- (CALL melee_damage target 40
- (+ 5
- (str caster)))))))))
-
-(SPELL () aggravate "#itenplz" ()
- (LET level 1)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 3)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level)))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (FOREACH MOB target
- (rbox
- (location caster)
- (+ 2
- (/ spellpower 50)))
- (IF (line_of_sight
- (location caster)
- (location target))
- (BLOCK
- (CALL sfx_generic target)
- (aggravate target 0 caster)))))))
-
-(SPELL () grow-mauve "#modrilax" ()
- (LET level 1)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 4)
- (CASTTIME 2000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "MauveHerb" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 6)
- (CALL summon_spell 1029
- (+
- (/
- (skill caster school)
- 2)
- 1)
- (- 4000
- (* spellpower 9))
- (+ 10000
- (* spellpower 50))
- 999999
- school))))
-
-(SPELL () grow-alizarin "#modriphoo" ()
- (LET level 1)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 4)
- (CASTTIME 2000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "AlizarinHerb" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 7)
- (CALL summon_spell 1032
- (+
- (/
- (skill caster school)
- 2)
- 1)
- (- 4000
- (* spellpower 9))
- (+ 10000
- (* spellpower 50))
- 999999
- school))))
-
-(SPELL () grow-gamboge "#modriyikam" ()
- (LET level 1)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 4)
- (CASTTIME 2000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "GambogeHerb" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 8)
- (CALL summon_spell 1031
- (+
- (/
- (skill caster school)
- 2)
- 1)
- (- 4000
- (* spellpower 9))
- (+ 10000
- (* spellpower 50))
- 999999
- school))))
-
-(SPELL () grow-cobalt "#modrisump" ()
- (LET level 1)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 4)
- (CASTTIME 2000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "CobaltHerb" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 9)
- (CALL summon_spell 1030
- (+
- (/
- (skill caster school)
- 2)
- 1)
- (- 4000
- (* spellpower 9))
- (+ 10000
- (* spellpower 50))
- 999999
- school))))
-
-(SPELL (LOCAL) summon-maggots "#kalmurk" ()
- (LET level 1)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 21)
- (CASTTIME 20000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (COMPONENTS "MaggotSlime" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL gain_xp 1 10)
- (CALL summon_spell 1002
- (+ 1
- (/
- (+
- (sqrt spellpower)
- (/ spellpower 15))
- 5))
- (- 5000
- (* spellpower 5))
- (+ 10000
- (* spellpower 50))
- 1
- school))))
-
-(SPELL () detect-magic "#miteyo" ()
- (LET level 1)
- (LET school MAGIC)
- (=>
- (GUARD
- (MANA 3)
- (CASTTIME 6000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level)))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (SET range
- (+ 1
- (/ spellpower 50)))
- (FOREACH NPC n
- (rbox
- (location caster)
- range)
- (IF (||
- (contains_string
- (name_of n)
- "#MAGIC")
- (contains_string
- (name_of n)
- "#_M"))
- (sfx n SFX_DEFAULT 0)))
- (FOREACH SPELL s (rbox
- (location caster)
- range) (IF (!= s self_invocation)
- (sfx s SFX_DEFAULT 0))))))
diff --git a/world/map/conf/magic-level2.sex b/world/map/conf/magic-level2.sex
deleted file mode 100644
index e4bd6908..00000000
--- a/world/map/conf/magic-level2.sex
+++ /dev/null
@@ -1,1462 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 2 spells "
-"--------------------------------------------------------------------------------"
-(SPELL () make-arrows "#kularzufrill" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 8)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "RawLog"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "Arrow"
- (+
- (+ 1
- (/ spellpower 40))
- (/
- (random
- (max 1
- (- 800 spellpower)))
- 80))
- "WarpedLog"
- 500)
- (CALL gain_xp 1 11))))
-
-(SPELL () make-shirt "#patmuploo" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 25)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS
- (5 "CottonCloth")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "CottonShirt" 1 "CottonCloth" 425)
- (CALL gain_xp 2 12))))
-
-(SPELL () make-tanktop "#patloree" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 25)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS
- (4 "CottonCloth")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "TankTop" 1 "CottonCloth" 350)
- (CALL gain_xp 2 13))))
-
-(SPELL () make-short-tanktop "#patviloree" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 25)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS
- (3 "CottonCloth")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "ShortTankTop" 1 "CottonCloth" 250)
- (CALL gain_xp 2 14))))
-
-(SPELL () make-iron-powder "#zukminbirf" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 8)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "IronOre"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "IronPowder"
- (+
- (+ 1
- (/ spellpower 140))
- (/
- (random
- (max 1
- (- 900 spellpower)))
- 220))
- "IronOre"
- 700)
- (CALL gain_xp 3 15))))
-
-(SPELL () make-concentration-potion "#loshira" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 8)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "BottleOfWater"
- (2 "CobaltHerb")
- (2 "PinkPetal")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item
- (if_then_else
- (<
- (random
- (+ 2000 experience))
- experience)
- "ConcentrationPotion"
- "DarkConcentrationPotion")
- 1
- (if_then_else
- (random 2)
- "DilutedConcentrationPot"
- "DarkConcentrationPotion")
- 2000)
- (IF success
- (CALL set_var MAGIC_FLAGS 1 MFLAG_MADE_CONC_POTION_SHIFT 1))
- (CALL gain_xp 4 16))))
-
-(SPELL () merge-concentration-potions "#skrimp" ()
- (LET level 2)
- (LET school TRANSMUTE)
- (=>
- (GUARD
- (MANA 8)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "DarkConcentrationPotion" "DilutedConcentrationPot"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL create_item "ConcentrationPotion" 1 "DilutedConcentrationPot" 1000)
- (message caster
- (+ "success = " success))
- (IF success
- (CALL set_var MAGIC_FLAGS 1 MFLAG_MADE_CONC_POTION_SHIFT 1))
- (CALL gain_xp 4 17))))
-
-(SPELL () lay-on-hands "#inma" (STRING target)
- (LET level 2)
- (LET school LIFE)
- (=>
- (GUARD
- (MANA 10)
- (CASTTIME 500)
- (REQUIRE
- (>
- (hp caster)
- (/
- (max_hp caster)
- 20)))
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (if_then_else
- (failed
- (pc target))
- 1
- (&&
- (&&
- (&&
- (!=
- (pc target)
- caster)
- (<
- (rdistance
- (location caster)
- (location
- (pc target)))
- (+ 2
- (/
- (+
- (* 12
- (sqrt spellpower))
- spellpower)
- 100))))
- (not
- (running_status_update
- (pc target)
- SC_HALT_REGENERATE)))
- (not
- (is_equipped
- (pc target)
- "MagicGMTopHat"))))))
- (EFFECT
- (CALL adjust_spellpower school)
- (IF (not target)
- (ABORT))
- (IF (failed
- (pc target))
- (BLOCK
- (IF (&&
- (||
- (== target "mouboo")
- (== target "Mouboo"))
- (<
- (rdistance
- (location caster)
- (location
- (npc "Mouboo")))
- (+ 2
- (/ spellpower 100))))
- (BLOCK
- (SET needed 1000)
- (SCRIPT "{
- set @spell, 1;
- callfunc \"QuestMoubooHeal\";
- }"))
- (ABORT)))
- (BLOCK
- (SET target
- (pc target))
- (SET needed
- (-
- (max_hp target)
- (hp target)))))
- (SET pay_fraction
- (max 80
- (- 200
- (+
- (vit caster)
- (/ spellpower 10))))) "Pay at least 40%"
- (SET payment
- (/
- (* needed pay_fraction)
- 200))
- (SET available
- (-
- (hp caster)
- (/
- (max_hp caster)
- 20)))
- (IF (< payment available)
- (SET power needed)
- (BLOCK
- (SET payment available)
- (SET power
- (/
- (* available 200)
- pay_fraction))))
- (CALL gain_heal_xp power 1 1 3)
- (CALL quickheal target power)
- (SET t 5000) "with dark magic skill you pay 1/20 of max hp but the regenerate cooldown is cut in half"
- (SET school DARK)
- (SET h
- (*
- (/
- (max_hp caster)
- 20)
- -1))
- (IF (>=
- (skill caster school)
- level)
- (itemheal caster h 0))
- (IF (>=
- (skill caster school)
- level)
- (SET t 10000))
- (status_change caster SC_HALT_REGENERATE 0 0 0 0 t)
- (CALL gain_xp
- (min 4
- (/ payment 100))
- 18))))
-
-(SPELL () lightning-strike "#ingrav" ()
- (LET level 2)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 20)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>=
- (skill caster school) "The spell is free at magic lv 4"
- 4))
- (COMPONENTS "IronPowder"))))
- (EFFECT
- (CALL adjust_spellpower school)
- (SET damage spellpower)
- (SET damage_bonus
- (+ 1
- (/ spellpower 2)))
- (CALL install_attack_spell
- (+ 1
- (/ spellpower 90))
- 3000
- 8
- 31)
- (CALL gain_xp 2 19)
- (ATTRIGGER
- (CALL attack_check target)
- (SET in_rain 0)
- (SET area
- (location caster))
- (FOREACH SPELL s (rbox
- (location caster)
- (+ MAX_RAIN_SPELL_RADIUS 1)) (IF (==
- (name_of s)
- "rain")
- (BLOCK
- (IF (is_in
- (location caster)
- (. s area))
- (BLOCK
- (SET in_rain
- (| in_rain 1))
- (SET area
- (+ area
- (. s area)))))
- (IF (is_in
- (location target)
- (. s area))
- (SET in_rain
- (| in_rain 2))))))
- (IF (& in_rain 1)
- (BLOCK "caster standing in the rain? This is going to be fun."
- (SET used 0)
- (FOREACH TARGET t area
- (IF (>
- (+
- (random 200)
- (luk caster))
- 175)
- (BLOCK
- (SET used
- (+ used 1))
- (CALL elt_damage t
- (/ damage 6)
- (+ 1
- (/ damage_bonus 3))
- ELT_EARTH
- ELT_WIND
- (+ 17
- (random 3))))))
- (IF (||
- (not used)
- (<
- (+
- (random 200)
- (luk caster))
- 150))
- (BLOCK
- (sfx caster
- (+ 17
- (random 3))
- 0)
- (itemheal caster
- (-
- (- 0 damage)
- (random damage_bonus))
- 0))))
- (CALL elt_damage target damage damage_bonus ELT_EARTH ELT_WIND
- (+ 17
- (random 3))))))))
-
-(SPELL (LOCAL) arrow-hail "#frillyar" ()
- (LET level 2)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 25)
- (CASTTIME 5000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (is_exterior
- (location caster)))
- (GUARD
- (OR
- (COMPONENTS
- (20 "Arrow"))
- (COMPONENTS
- (20 "IronArrow"))))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "SulphurPowder"))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL abort_on_area_shield
- (location caster))
- (SET range 7)
- (SET area
- (rbox
- (awayfrom
- (location caster)
- (dir caster)
- (+ 1 range))
- range))
- (FOREACH SPELL s (rbox
- (awayfrom
- (location caster)
- (dir caster)
- (+ 1 range))
- (* range 2)) (IF (&&
- (!= s self_invocation)
- (==
- (name_of s)
- "arrow-hail"))
- (BLOCK
- (message caster "A nearby arrow hail spell absorbs your magic!")
- (ABORT))))
- (SET damage 125)
- (SET damage_bonus
- (/ spellpower 5))
- (CALL gain_xp 2 20)
- (FOR i 0
- (/ spellpower 8)
- (BLOCK
- (IF (not (pc caster))
- (ABORT))
- (FOR j 0 2
- (BLOCK
- (IF (not (pc caster))
- (ABORT))
- (SET location
- (random_location area))
- (sfx location SFX_ARROW_HAIL 0)
- (SET done 0)
- (FOREACH TARGET target
- (rbox location 0)
- (BLOCK
- (injure caster target
- (+
- (+ damage
- (random damage_bonus))
- (random damage_bonus))
- 0)
- (SET done 1)
- (BREAK)))
- (IF (&&
- (==
- (location caster)
- location)
- (not done))
- (BLOCK
- (itemheal caster
- (- 0
- (+
- (+ damage
- (random damage_bonus))
- (random damage_bonus)))
- 0)
- (sfx caster SFX_HIT 0)))))
- (WAIT
- (+
- (+ 250
- (random 50))
- (random 50))))))))
-
-(SPELL () magic-knuckles "#upmarmu" ()
- (LET level 2)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 20)
- (CASTTIME 500)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "Beer"))))
- (EFFECT
- (CALL adjust_spellpower WAR)
- (SET str
- (str caster))
- (CALL install_melee_spell
- (+ 10
- (/ spellpower 10))
- 1300
- 34)
- (ATTRIGGER
- (CALL melee_damage target 30
- (+ 5
- (* str 2)))))))
-
-(SPELL (LOCAL) summon-snakes "#halhiss" ()
- (LET level 2)
- (LET school DARK)
- (=>
- (GUARD
- (MANA 40)
- (CASTTIME 15000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (>
- (script_int caster "OrumQuest")
- 40))
- (COMPONENTS "DarkCrystal" "SnakeEgg"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 3 31)
- (CALL summon_spell 1010
- (+ 1
- (/ spellpower 300))
- (- 4000
- (* spellpower 9))
- (* spellpower 80)
- 2
- school))))
-
-(SPELL () toxic-dart "#phlex" ()
- (LET level 2)
- (LET school DARK)
- (=>
- (GUARD
- (MANA 15)
- (CASTTIME 500)
- (REQUIRE
- (>
- (script_int caster "OrumQuest")
- 37))
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>=
- (skill caster school)
- 3))
- (COMPONENTS
- (2 "Root")))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (SET damage
- (* 5
- (sqrt spellpower)))
- (SET damage_bonus
- (+ 5
- (/
- (level caster)
- 3)))
- (CALL install_attack_spell
- (+ 3
- (/ spellpower 75))
- 1200
- 4
- 31)
- (CALL gain_xp 3 35)
- (ATTRIGGER
- (CALL attack_check target)
- (CALL elt_damage target damage damage_bonus ELT_NEUTRAL ELT_POISON 15)
- (IF (&&
- (is_pc target)
- (!= caster target))
- (status_change target SC_POISON
- (+ 5
- (max 15
- (/ spellpower 15)))
- 0
- 0
- 0
- (+ 5000
- (* spellpower 1200))))))))
-
-(SPELL (LOCAL) summon-wickedmushroom "#helorp" ()
- (LET level 2)
- (LET school DARK)
- (=>
- (GUARD
- (MANA 35)
- (CASTTIME 15000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>
- (script_int caster "OrumQuest")
- 36))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "SmallMushroom" "DarkCrystal"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 3 36)
- (CALL summon_spell 1106
- (+ 1
- (/ spellpower 250))
- (- 4000
- (* spellpower 9))
- (* spellpower 80)
- 2
- school))))
-
-(SPELL () flying-backpack "#plugh" (PC target)
- (LET level 2)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 12)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "SilkCocoon")))
- (REQUIRE
- (<
- (rdistance
- (location target)
- (location caster))
- (+ 2
- (/ spellpower 30)))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (!= caster target)
- (sfx caster 2 0))
- (status_change target SC_FLYING_BACKPACK 0 0 0 0
- (+ 5000
- (* spellpower 500)))
- (message target "Your backpack is lifted by a mystical force; you no longer feel it pressing on your back.")
- (CALL gain_xp 1 21)
- (ATEND
- (message target "Your backpack is no longer levitating.")
- (sfx target 2 0)))))
-
-(SPELL () protect "#betsanc" (PC target)
- (LET level 2)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 14)
- (CASTTIME 1500)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (not
- (is_equipped
- (pc target)
- "MagicGMTopHat")))
- (GUARD
- (OR
- (REQUIRE
- (>=
- (skill caster school)
- 4))
- (COMPONENTS "HardSpike")))
- (REQUIRE
- (<
- (rdistance
- (location target)
- (location caster))
- (+ 2
- (/ spellpower 30)))))
- (EFFECT
- (CALL adjust_spellpower school)
- (sfx target 11 0)
- (IF (!= caster target)
- (CALL default_effect))
- (status_change target SC_PHYS_SHIELD
- (+ 5
- (max 15
- (/ spellpower 20)))
- 0
- 0
- 0
- (+ 5000
- (* spellpower 1000)))
- (message target "You feel more protected.")
- (CALL gain_xp 2 22)
- (ATEND
- (message target "You feel less protected.")
- (sfx target 111 0)))))
-
-(SPELL () happy-curse "#joyplim" (PC target)
- (LET level 2)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 13)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "GingerBreadMan")))
- (REQUIRE
- (<
- (rdistance
- (location target)
- (location caster))
- (+ 1
- (/ spellpower 100)))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (>
- (skill caster DARK)
- 1)
- (FOR i 0
- (/ spellpower 10)
- (BLOCK
- (emote target 5)
- (WAIT 500)))
- (FOR i 0
- (/ spellpower 10)
- (BLOCK
- (emote target 3)
- (WAIT 500))))
- (CALL gain_xp 1 23))))
-
-(SPELL (LOCAL) rain "#kaflosh" ()
- (LET level 2)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 17)
- (CASTTIME 3000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (is_exterior
- (location caster)))
- (GUARD
- (OR
- (REQUIRE
- (>=
- (skill caster school)
- 4))
- (COMPONENTS "BottleOfWater"))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL abort_on_area_shield
- (location caster))
- (FOREACH SPELL s (rbox
- (location caster)
- (+ MAX_RAIN_SPELL_RADIUS 1)) (IF (&&
- (!= s self_invocation)
- (==
- (name_of s)
- "rain"))
- (BLOCK
- (message caster "A nearby raincloud absorbs your magic.")
- (ABORT))))
- (CALL gain_xp 1 24)
- (SET range
- (min MAX_RAIN_SPELL_RADIUS
- (+ 3
- (/
- (min spellpower 200)
- 30))))
- (SET area
- (rbox
- (location caster)
- range))
- (IF (||
- (is_in
- (location
- (npc "#DruidTree0#_M"))
- area)
- (is_in
- (location
- (npc "#DruidTree1#_M"))
- area))
- (SCRIPT "{
- set @flag, 1;
- callfunc \"QuestTreeTrigger\";
- close;
- }"))
- (IF (is_in
- (location caster)
- (@+
- (@ "011-1" 94 38)
- 9
- 7))
- (SCRIPT "{
- callfunc \"HalloweenQuestWaterPumpkins\";
- }")) "Halloween quest"
- (FOR i 0
- (/ spellpower 3)
- (BLOCK
- (IF (not (pc caster))
- (ABORT))
- (FOR j 0
- (/
- (min
- (/ spellpower 2)
- 200)
- 100)
- (BLOCK
- (IF (not (pc caster))
- (ABORT))
- (SET location
- (random_location area))
- (sfx location SFX_RAIN 0)
- (FOREACH TARGET target
- (rbox location 1)
- (IF (==
- (element target)
- ELT_FIRE)
- (injure caster target
- (+ 2
- (random
- (+ 5
- (/ spellpower 15))))
- 0)))))
- (WAIT
- (+ 400
- (random 100))))))))
-
-(PROCEDURE shear-drop (target target2 item prob)
- (IF (||
- (== target name)
- (== target2 name))
- (BLOCK
- (IF (< score prob)
- (drop_item_for place item 1 60000 caster 5000)))))
-
-(PROCEDURE shear-drop2 (target target2 item prob item2 prob2)
- (IF (||
- (== target name)
- (== target2 name))
- (BLOCK
- (IF (< score prob)
- (drop_item_for place item 1 60000 caster 5000)
- (CALL shear-drop target target2 item2
- (+ prob2 prob))))))
-
-(PROCEDURE shear-drop3 (target target2 item prob item2 prob2 item3 prob3)
- (IF (||
- (== target name)
- (== target2 name))
- (BLOCK
- (IF (< score prob)
- (drop_item_for place item 1 60000 caster 5000)
- (CALL shear-drop2 target target2 item2
- (+ prob2 prob)
- item3
- (+ prob3 prob))))))
-
-(SPELL () shear "#chipchip" ()
- (LET level 2)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 23)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level)))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (override_attack caster 1 2000 1 ATTACK_ICON_SHEARING 30 0)
- (ATTRIGGER
- (IF (not
- (is_pc target))
- (BLOCK
- (SET score
- (random
- (- 1000
- (random spellpower)))) "lower score -> more valuable item"
- (SET name
- (name_of target))
- (SET place
- (random_location
- (rbox
- (location target)
- 1)))
- (IF (running_status_update target SC_SHEARED)
- (ABORT))
- (status_change target SC_SHEARED 0 0 0 0 600000) "10 minutes"
- (CALL shear-drop "Fluffy" "Fluffy" "WhiteFur" 300)
- (CALL shear-drop "EasterFluffy" "Easter Fluffy" "WhiteFur" 300)
- (CALL shear-drop "SpikyMushroom" "Spiky Mushroom" "HardSpike" 250)
- (CALL shear-drop "Mouboo" "Mouboo" "CottonCloth" 175)
- (CALL shear-drop "Cobalt" "CobaltPlant" "CobaltHerb" 700)
- (CALL shear-drop "Alizarin" "AlizarinPlant" "AlizarinHerb" 700)
- (CALL shear-drop "Gamboge" "GambogePlant" "GambogeHerb" 700)
- (CALL shear-drop "Mauve" "MauvePlant" "MauveHerb" 700)
- (CALL shear-drop "SilkWorm" "Silkworm" "SilkCocoon" 300)
- (CALL shear-drop "Pinkie" "Pinkie" "PinkAntenna" 180)
- (IF (&&
- (||
- (||
- (== name "Fluffy")
- (== name "Mouboo"))
- (== name "Pinkie"))
- (random 2))
- (SCRIPT "{
- set @value, 1;
- callfunc \"QuestSagathaHappy\";
- }"))))))))
-
-(SPELL () barrier "#asorm" (PC target)
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 16)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (not
- (is_equipped
- (pc target)
- "MagicGMTopHat")))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "SmallMushroom")))
- (REQUIRE
- (<
- (rdistance
- (location target)
- (location caster))
- (+ 2
- (/ spellpower 30)))))
- (EFFECT
- (CALL adjust_spellpower school)
- (sfx target SFX_BARRIER 0)
- (IF (!= caster target)
- (CALL default_effect))
- (status_change target SC_MBARRIER
- (+ 20
- (max 30
- (/ spellpower 8)))
- 0
- 0
- 0
- (+ 2000
- (* spellpower 200)))
- (message target "You are surrounded by a magical barrier.")
- (CALL gain_xp 3 25)
- (ATEND
- (message target "Your magical barrier dissipates.")
- (sfx target SFX_UNBARRIER 0)))))
-
-(SPELL (LOCAL) summon-spiky-mushrooms "#kalrenk" ()
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 33)
- (CASTTIME 20000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "HardSpike" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 26)
- (CALL summon_spell 1019
- (+ 1
- (/ spellpower 120))
- (- 5000
- (* spellpower 9))
- (* spellpower 400)
- 2
- school))))
-
-(SPELL (LOCAL) summon-fluffies "#kalakarenk" ()
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 39)
- (CASTTIME 20000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "WhiteFur" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 1 27)
- (CALL summon_spell 1020
- (+
- (+ 1
- (/ spellpower 170))
- (/ spellpower 430))
- (- 5000
- (* spellpower 8))
- (* spellpower 350)
- 2
- school))))
-
-(SPELL (LOCAL) summon-mouboo "#kalboo" ()
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 35)
- (CASTTIME 20000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "MoubooFigurine" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 2 37)
- (CALL summon_spell 1028
- (+ 1
- (/ spellpower 270))
- (- 4000
- (* spellpower 9))
- (* spellpower 100)
- 2
- school))))
-
-(SPELL (LOCAL) summon-pinkie "#kalgina" ()
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 35)
- (CASTTIME 20000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "PinkAntenna" "Root"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (CALL gain_xp 2 38)
- (CALL summon_spell 1018
- (+ 1
- (/ spellpower 120))
- (- 5000
- (* spellpower 9))
- (* spellpower 150)
- 2
- school))))
-
-(SPELL () detect-players "#inwilt" ()
- (LET level 2)
- (LET school MAGIC)
- (=>
- (GUARD
- (MANA 7)
- (CASTTIME 300)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level)))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (SET message "")
- (FOREACH PC target
- (rbox
- (location caster)
- (/ spellpower 2))
- (IF (&&
- (&&
- (!= target caster)
- (not
- (running_status_update
- (pc target)
- SC_HIDE)))
- (not
- (status_option target SO_GMINVISIBLE)))
- (BLOCK
- (IF (!= message "")
- (SET message
- (+ message ", ")))
- (SET message
- (+ message
- (name_of target)))
- (IF (> spellpower 99)
- (SET message
- (+
- (+
- (+ message "(")
- (level target))
- ")"))))))
- (IF (== message "")
- (message caster "You sense no-one else nearby.")
- (message caster
- (+ "You sense the following: " message))))))
-
-(SPELL () enchant-lifestone "#manpahil" ()
- (LET level 2)
- (LET school MAGIC)
- (=>
- (GUARD
- (MANA 15)
- (CASTTIME 4000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (OR
- (COMPONENTS "BugLeg")
- (COMPONENTS "MaggotSlime"))
- (COMPONENTS "MauveHerb" "AlizarinHerb" "CobaltHerb" "GambogeHerb"))))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (create_item caster "Lifestone" 1)
- (CALL gain_xp 1 28))))
-
-(SPELL () sense-spouse "#inzuwilt" ()
- (LET level 2)
- (LET school MAGIC)
- (=>
- (GUARD
- (MANA 7)
- (CASTTIME 400)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (is_married caster))
- (REQUIRE
- (is_equipped caster "WeddingRing")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (||
- (failed
- (partner caster))
- (not
- (is_equipped
- (partner caster)
- "WeddingRing")))
- (BLOCK
- (message caster "You cannot sense your partner.")
- (ABORT)))
- (SET partner
- (partner caster))
- (SET name
- (name_of partner))
- (IF (||
- (is_dead partner)
- (!=
- (map_nr
- (location partner))
- (map_nr
- (location caster))))
- (BLOCK
- (message caster
- (+
- (+ "You cannot sense " name)
- " nearby."))
- (ABORT)))
- (IF (&&
- (>
- (map_level
- (location partner))
- 2)
- (<
- (map_level
- (location caster))
- (map_level
- (location partner))))
- (BLOCK
- (message caster
- (+
- (+ "You sense " name)
- " somewhere below."))
- (ABORT)))
- (IF (&&
- (>
- (map_level
- (location caster))
- 2)
- (<
- (map_level
- (location partner))
- (map_level
- (location caster))))
- (BLOCK
- (message caster
- (+
- (+ "You sense " name)
- " somewhere above."))
- (ABORT)))
- (IF (!=
- (map_level
- (location caster))
- (map_level
- (location partner)))
- (message caster
- (+
- (+ "You sense " name)
- " somewhere in the vincinity."))
- (BLOCK
- (SET distance
- (rdistance
- (location caster)
- (location partner)))
- (SET dir
- (dir_towards
- (location caster)
- (location partner)
- 1))
- (IF (< distance 3)
- (message caster
- (+
- (+ "You sense " name)
- " right next to you."))
- (IF (< distance 30)
- (message caster
- (+
- (+
- (+
- (+ "You sense " name)
- " close by, towards the ")
- dir)
- "."))
- (IF (< distance 200)
- (message caster
- (+
- (+
- (+
- (+ "You sense " name)
- " nearby, towards the ")
- dir)
- "."))
- (message caster
- (+
- (+
- (+
- (+ "You sense " name)
- " in the ")
- dir)
- "."))))))))))
-
-(SPELL () hide "#anwiltyp" (PC target)
- (LET level 2)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 11)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (GUARD
- (OR
- (REQUIRE
- (>
- (skill caster school)
- 3))
- (COMPONENTS "CottonCloth")))
- (REQUIRE
- (<
- (rdistance
- (location target)
- (location caster))
- (+ 2
- (/ spellpower 30)))))
- (EFFECT
- (CALL adjust_spellpower school)
- (sfx target SFX_DEFAULT 0)
- (IF (!= caster target)
- (CALL default_effect))
- (status_change target SC_HIDE 0 0 0 0
- (+ 5000
- (* spellpower 2500)))
- (CALL gain_xp 2 29)
- (message target "You are hidden!")
- (IF (!= caster target)
- (message caster "You hid someone!"))
- (ATEND
- (message target "You are no longer hidden.")))))
diff --git a/world/map/conf/magic-level3.sex b/world/map/conf/magic-level3.sex
deleted file mode 100644
index 5d4d7374..00000000
--- a/world/map/conf/magic-level3.sex
+++ /dev/null
@@ -1,179 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 3 spells "
-"--------------------------------------------------------------------------------"
-(DISABLED
- (SPELL () cure-poison "#anju" (PC target)
- (LET level 3)
- (LET school LIFE)
- (=>
- (GUARD
- (MANA 15)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (<
- (rdistance
- (location caster)
- (location
- (pc target)))
- (+ 1
- (/ spellpower 60))))
- (COMPONENTS "GambogeHerb"))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (running_status_update target SC_POISON)
- (BLOCK
- (CALL gain_heal_xp 40 1 2 2)
- (stop_status_change target SC_POISON)
- (CALL gain_xp 2 30)
- (IF (!= caster target)
- (sfx target SFX_HEAL 0))))))))
-
-(DISABLED
- (SPELL () fire-ball "#flarfol" ()
- (LET level 3)
- (LET school WAR)
- (=>
- (GUARD
- (MANA 30)
- (CASTTIME 1000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (COMPONENTS "PileOfAsh"))
- (EFFECT
- (CALL adjust_spellpower school)
- (SET damage
- (min
- (+ 50
- (*
- (skill caster school)
- 40))
- (+ 30
- (/
- (* spellpower 3)
- 2))))
- (SET damage_bonus
- (+
- (level caster)
- (* spellpower 2)))
- (SET radius
- (+ 2
- (/ spellpower 50)))
- (CALL install_attack_spell
- (+ 1
- (/ spellpower 60))
- 5000
- 10
- 31)
- (ATTRIGGER
- (CALL attack_check target)
- (SET loc
- (location target))
- (DISABLED (WAIT 500))
- (sfx loc 16 0)
- (FOREACH TARGET target
- (rbox loc radius)
- (IF (line_of_sight loc
- (location target))
- (BLOCK
- (SET divisor
- (+ 3
- (rdistance loc
- (location target))))
- (CALL elt_damage target
- (/
- (* damage 3)
- divisor)
- (/
- (* damage_bonus 3)
- divisor)
- ELT_WATER
- ELT_FIRE
- 15)))))))))
-
-(DISABLED
- (SPELL () summon-partner "#kalzumin" ()
- (LET level 3)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 30)
- (CASTTIME 2000)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level))
- (REQUIRE
- (is_married caster))
- (REQUIRE
- (is_equipped caster "WeddingRing")))
- (EFFECT
- (CALL adjust_spellpower school)
- (CALL default_effect)
- (IF (failed
- (partner caster))
- (message caster "You call out for your partner, but there is no response.")
- (BLOCK
- (message caster
- (+
- (+ "You call out for "
- (name_of
- (partner caster)))
- "."))
- (message
- (partner caster)
- (+
- (name_of caster)
- " is calling for your aid!"))
- (sfx
- (partner caster)
- 2
- 0)
- (WAIT
- (max 5000
- (- 30000
- (* spellpower 60))))
- (IF (failed
- (partner caster))
- (message caster "Your partner has abandoned you.")
- (IF (is_dead
- (partner caster))
- (message caster
- (+
- (+ "Something seems to have happened to "
- (name_of
- (partner caster)))
- "."))
- (BLOCK
- (sfx
- (location
- (partner caster))
- SFX_TELEPORT
- 0)
- (SET dest
- (awayfrom
- (location caster)
- (random_dir 1)
- 1))
- (warp
- (partner caster)
- dest)
- (sfx dest SFX_TELEPORT 0))))))))))
diff --git a/world/map/conf/magic-level4.sex b/world/map/conf/magic-level4.sex
deleted file mode 100644
index f04092f4..00000000
--- a/world/map/conf/magic-level4.sex
+++ /dev/null
@@ -1,3 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 4 spells "
-"--------------------------------------------------------------------------------"
diff --git a/world/map/conf/magic-level5.sex b/world/map/conf/magic-level5.sex
deleted file mode 100644
index 056c9e50..00000000
--- a/world/map/conf/magic-level5.sex
+++ /dev/null
@@ -1,55 +0,0 @@
-"--------------------------------------------------------------------------------"
-" Level 5 spells "
-"--------------------------------------------------------------------------------"
-(DISABLED
- (SPELL () shroud "#anwilvimar" ()
- (LET level 5)
- (LET school NATURE)
- (=>
- (GUARD
- (MANA 40)
- (CASTTIME 400)
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level)))
- (EFFECT
- (CALL default_effect)
- (shroud caster 0x04)))))
-
-(DISABLED
- (SPELL () teleport "#vorp" (STRING destination)
- (LET level 5)
- (LET school ASTRAL)
- (=>
- (GUARD
- (MANA 80)
- (CASTTIME 400)
- (COMPONENT "EtherEssence")
- (CATALYSTS "TeleportCrystal")
- (REQUIRE
- (>=
- (skill caster MAGIC)
- level))
- (REQUIRE
- (>=
- (skill caster school)
- level)))
- (EFFECT
- (CALL default_effect)
- (WAIT
- (+ 1000
- (/ 200000
- (+ spellpower 10))))
- (sfx
- (location caster)
- SFX_TELEPORT
- 200)
- (warp caster
- (random_location
- (anchor destination)))
- (sfx caster SFX_TELEPORT 200)))))
diff --git a/world/map/conf/magic-misc.sex b/world/map/conf/magic-misc.sex
index 15672f4c..14d6ea3a 100644
--- a/world/map/conf/magic-misc.sex
+++ b/world/map/conf/magic-misc.sex
@@ -1,68 +1,6 @@
"--------------------------------------------------------------------------------"
" Special-purpose quasispells "
"--------------------------------------------------------------------------------"
-(SPELL (NONMAGIC) dueloff "#dueloff" ()
- (=>
- (GUARD
- (REQUIRE
- (== (substr (location caster) 2 5) "009-7")))
- (EFFECT
- (IF (== (script_int caster "@Duels_Off") 1)
- (BLOCK
- (SCRIPT "{set @Duels_Off, 0;}")
- (message caster "Now accepting incoming duel requests.")
- (ABORT)))
- (SCRIPT "{set @Duels_Off, 1;}")
- (message caster "Now blocking incoming duel requests."))))
-
-(SPELL (NONMAGIC) duel "#duel" (PC target)
- (=>
- (GUARD
- (REQUIRE
- (== (& (script_int target "$SANGUINE") (script_int target "$@SV_FCDBit")) 0)))
- (EFFECT
- (IF (== target caster)
- (BLOCK
- (message caster "You can not fight against yourself.")
- (ABORT)))
- (IF (is_dead target)
- (BLOCK
- (message caster "You can not fight against a corpse.")
- (ABORT)))
- (IF (status_option caster SO_GMINVISIBLE)
- (BLOCK
- (message caster "You can not fight while being invisible.")
- (ABORT)))
- (IF (status_option target SO_GMHIDE)
- (BLOCK
- (message caster "This player have @hide enabled.")
- (ABORT)))
- (IF (status_option target SO_GMINVISIBLE)
- (ABORT))
- (IF (status_option caster SO_GMHIDE)
- (ABORT))
- (IF (!= (substr (location caster) 2 5) "009-7")
- (BLOCK
- (message caster "You need to be in the fight club to challenge someone to a duel.")
- (ABORT)))
- (IF (!= (substr (location target) 2 5) "009-7")
- (BLOCK
- (message caster "This player is not in the fight club at the moment.")
- (ABORT)))
- (IF (> (script_int target "@Duels_Off") 0)
- (BLOCK
- (message caster "This player is automatically ignoring incoming duel requests.")
- (ABORT)))
- (IF (> (script_int caster "$@Duel_Queue_ID[($@Duel_QueueLimit)]") 0)
- (BLOCK
- (message caster (+ (+ "There is already " (script_int caster "$@Duel_QueueLimit")) " duel(s) in the queue, which is the maximum."))
- (ABORT)))
- (IF (> (script_int target "@Duel_Queue[($@Duel_PlayerQueueLimit)]") 0)
- (BLOCK
- (message caster (+ (+ "There is already " (script_int caster "$@Duel_PlayerQueueLimit")) " duel request(s) in the queue of this player, which is the maximum."))
- (ABORT)))
- (SET script_target target)
- (SCRIPT "{callfunc \"fightclub_sendrequest\";}"))))
(SPELL (NONMAGIC SILENT) marriage "marry" (PC target)
(=>
@@ -165,53 +103,3 @@
(+
(name_of target)
" turned down your marriage offer."))))))
-
-(DISABLED
- (SPELL (LOCAL) mouboo-groan "#g" ()
- (=>
- (GUARD
- (MANA 1)
- (REQUIRE
- (==
- (name_of caster)
- "MOUBOOTAUR")))
- (EFFECT
- (FOREACH PC p
- (rbox
- (location caster)
- 200)
- (SET distance
- (rdistance
- (location caster)
- (location p))))
- (IF (< distance 15)
- (message p "The moubootaur's groaning rings in your ears!")
- (IF (< distance 70)
- (message p "You hear a loud groaning noise, not far away...")
- (message p "You hear an odd groaning noise in the distance...")))))))
-
-(DISABLED
- (SPELL (LOCAL) mouboo-smell "#s" ()
- (=>
- (GUARD
- (MANA 1)
- (REQUIRE
- (==
- (name_of caster)
- "MOUBOOTAUR")))
- (EFFECT
- (WAIT 30000)
- (FOREACH PC p
- (rbox
- (location caster)
- 30)
- (message p "You notice a strange smell all around you."))))))
-
-(SPELL (NONMAGIC) killgm0 "#pullrabbit" ()
- (=>
- (REQUIRE
- (is_equipped caster "MagicGMTopHat"))
- (EFFECT
- (SCRIPT "{
- callfunc \"ActivateMagicGMTophat\";
- }"))))
diff --git a/world/map/conf/magic-procedures.sex b/world/map/conf/magic-procedures.sex
index ea62f50f..0ba40bc8 100644
--- a/world/map/conf/magic-procedures.sex
+++ b/world/map/conf/magic-procedures.sex
@@ -286,12 +286,7 @@
(WAIT delay)
(sfx location SFX_SUMMON_FIRE 0)
(spawn
- (rbox location (if_then_else
- (is_in (location caster)
- (@+
- (@ "009-7" (- (script_int caster "$@fightclub_x1") 2) (- (script_int caster "$@fightclub_y1") 2))
- (+ (- (script_int caster "$@fightclub_x2") (script_int caster "$@fightclub_x1")) 5)
- (+ (- (script_int caster "$@fightclub_y2") (script_int caster "$@fightclub_y1")) 5))) 1 2))
+ (rbox location 2)
caster
mob_id
(if_then_else
diff --git a/world/map/conf/magic-quests.sex b/world/map/conf/magic-quests.sex
deleted file mode 100644
index 4b8a822c..00000000
--- a/world/map/conf/magic-quests.sex
+++ /dev/null
@@ -1,154 +0,0 @@
-(PROCEDURE hug_tree (target)
- (IF (||
- (||
- (||
- (||
- (||
- (||
- (||
- (||
- (== target "")
- (== target "tree"))
- (== target "tree*"))
- (== target "Tree"))
- (== target "Tree*"))
- (== target "druid"))
- (== target "druid*"))
- (== target "Druid"))
- (== target "Druid*"))
- (SCRIPT "{
- set @flag, 2;
- callfunc \"QuestTreeTrigger\";
- close;
- }")))
-
-(SPELL (NONMAGIC) hug0 "hug" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-(SPELL (NONMAGIC) hug1 "*hug*" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-(SPELL (NONMAGIC) hug2 "*hug" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-(SPELL (NONMAGIC) hug3 "hugs" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-(SPELL (NONMAGIC) hug4 "*hugs*" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-(SPELL (NONMAGIC) hug5 "*hugs" (STRING target)
- (=>
- (REQUIRE
- (||
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree0#_M")))
- 1)
- (<=
- (rdistance
- (location caster)
- (location
- (npc "#DruidTree1#_M")))
- 1)))
- (EFFECT
- (CALL hug_tree target))))
-
-"--------------------------------------------------------------------------------"
-"Illia spell"
-"--------------------------------------------------------------------------------"
-(SPELL (NONMAGIC) illia0 "#catalazuli" ()
- (=>
- (REQUIRE
- (==
- (rdistance
- (location caster)
- (location
- (npc "#Power Circle")))
- 0))
- (EFFECT
- (SCRIPT "{
- callfunc \"StartChannelling\";}
- "))))
diff --git a/world/map/conf/tmwa-map.conf b/world/map/conf/tmwa-map.conf
index 849779af..fa28abe5 100644
--- a/world/map/conf/tmwa-map.conf
+++ b/world/map/conf/tmwa-map.conf
@@ -9,7 +9,9 @@ map_conf: conf/map_athena.conf
battle_conf: conf/battle_athena.conf
atcommand_conf: conf/atcommand_athena.conf
+const_db: db/params.txt
const_db: db/const.txt
+const_db: db/const-magic.txt
const_db: db/const-quest.txt
const_db: db/const-mapflags.txt
const_db: db/const-debugflag.txt
@@ -35,19 +37,4 @@ mob_db: db/mob_db_over_100.txt
mob_skill_db: db/mob_skill_db.txt
skill_db: db/skill_db.txt
-magic_conf: conf/magic-config.sex
-magic_conf: conf/magic-procedures.sex
-magic_conf: conf/magic-level0.sex
-magic_conf: conf/magic-level1.sex
-magic_conf: conf/magic-level2.sex
-magic_conf: conf/magic-level3.sex
-magic_conf: conf/magic-level4.sex
-magic_conf: conf/magic-level5.sex
-magic_conf: conf/magic-misc.sex
-magic_conf: conf/magic-quests.sex
-magic_conf: conf/magic-anchors.sex
-magic_conf: conf/magic-quickdebug.sex
-
-magic_conf: conf/magic-secrets.sex
-
resnametable: data/resnametable.txt
diff --git a/world/map/db/const-magic.txt b/world/map/db/const-magic.txt
new file mode 100644
index 00000000..9bf8e063
--- /dev/null
+++ b/world/map/db/const-magic.txt
@@ -0,0 +1,62 @@
+// NOTE: I think min_casttime should be in battle config if we don't make it a variable
+MIN_CASTTIME 200
+
+// Magic Skills
+SKILL_MAGIC 340
+SKILL_MAGIC_LIFE 341
+SKILL_MAGIC_WAR 342
+SKILL_MAGIC_TRANSMUTE 343
+SKILL_MAGIC_NATURE 344
+SKILL_MAGIC_ASTRAL 345
+SKILL_MAGIC_DARK 346
+
+// Elements
+ELT_NEUTRAL 0
+ELT_WATER 1
+ELT_EARTH 2
+ELT_FIRE 3
+ELT_WIND 4
+ELT_POISON 5
+ELT_SHADOW 6
+ELT_HOLY 7
+ELT_GHOST 8
+ELT_UNDEAD 9
+
+// Status effects
+SC_SHEARED 194
+SC_HIDE 194
+SC_HALT_REGENERATE 195
+SC_FLYING_BACKPACK 196
+SC_MBARRIER 197
+SC_HASTE 198
+SC_PHYS_SHIELD 199
+SO_GMHIDE 64
+SO_GMINVISIBLE 4096
+
+// Special effects
+SFX_DEFAULT 10
+SFX_SUMMON_START 21
+SFX_SUMMON_FIRE 22
+SFX_TELEPORT 24
+SFX_RAIN 25
+SFX_HIT 25
+SFX_ARROW_HAIL 27
+SFX_BARRIER 10
+SFX_UNBARRIER 10
+SFX_HEAL 3
+SFX_LIGHTNING 18
+
+// Magic Spell Const
+MIN_MARRY_LEVEL 32
+MAX_RAIN_SPELL_RADIUS 15
+MAX_MAGIC_LEVEL 2
+MFLAG_MADE_CONC_POTION 16384
+MFLAG_MADE_CONC_POTION_SHIFT 14
+// SCRIPT_XP "MAGIC_EXPERIENCE"
+SCRIPT_XP_MASK 65535
+SCRIPT_XP_SHIFT 0
+SCRIPT_HEALSPELL_MASK 255
+SCRIPT_HEALSPELL_SHIFT 24
+ATTACK_ICON_GENERIC 2000
+ATTACK_ICON_SHEARING 2001
+E10_FLAG_USED_FREE_WARP_SHIFT 17
diff --git a/world/map/db/const.txt b/world/map/db/const.txt
index d3b42ee4..2f7d63a8 100644
--- a/world/map/db/const.txt
+++ b/world/map/db/const.txt
@@ -1,39 +1,6 @@
// Constants usable in scripts.
+// TODO remove all the bSomething and move them to params instead
-// BEFORE UNCOMMENTING ANYTHING, TALK TO o11c!
-
-// Note: the type-1 constants and the bWhatever are actually
-// the same type internally, but they must be used differently.
-// A *few* can be used for both ...
-// TODO resolve that last, and change the names to match SP_*
-
-// BEFORE UNCOMMENTING ANYTHING, TALK TO o11c!
-//BaseExp 1 1
-//JobExp 2 1
-Hp 5 1
-MaxHp 6 1
-Sp 7 1
-MaxSp 8 1
-StatusPoint 9 1
-BaseLevel 11 1
-//SkillPoint 12 1
-Class 19 1
-Zeny 20 1
-Sex 21 1
-//NextBaseExp 22 1
-//NextJobExp 23 1
-Weight 24 1
-MaxWeight 25 1
-//JobLevel 55 1
-//Upper 56 1
-Str 13 1
-Agi 14 1
-Vit 15 1
-Int 16 1
-Dex 17 1
-Luk 18 1
-
-// BEFORE UNCOMMENTING ANYTHING, TALK TO o11c!
bMaxHP 6
bMaxSP 8
bStr 13
@@ -44,7 +11,7 @@ bDex 17
bLuk 18
//bAtk 41
//bAtk2 42
-//bMatk1 43
+bMatk1 43
//bMatk2 44
//bDef 45
bMdef 47
@@ -102,8 +69,6 @@ bDeaf 70
// Those which can be used with the arrow are only bCritical, bAtkEle, bHit, bAddEle, bAddRace, bAddSize and bAddEff. The other bonuses are ignored.
// For more information, have a look here: http://code.google.com/p/eathena/source/browse/trunk/doc/item_bonus.txt
-// BEFORE UNCOMMENTING ANYTHING, TALK TO o11c!
-
bAtkRange 1000 // A range bonus of n (bAtkRange,n;).
//bAtkEle 1001 // Gives the player's attacks a n element (bAtkEle,n;).
//bDefEle 1002 // Gives the player's defense a n element (bDefEle,n;).
@@ -265,6 +230,13 @@ sc_poison 132
sc_slowpoison 14
sc_raiseattackspeed0 37
sc_raiseattackstrength 185
+SC_SHEARED 194
+SC_HIDE 194
+SC_HALT_REGENERATE 195
+SC_FLYING_BACKPACK 196
+SC_MBARRIER 197
+SC_HASTE 198
+SC_PHYS_SHIELD 199
// Emotions
EMOTE_DISGUST 1
@@ -311,6 +283,11 @@ EMOTE_TROLL 126
EMOTE_PAIN 127
EMOTE_TEARS 128
+// symbols used for registercmd (ASCII)
+MAGIC_SYMBOL 35
+ATCMD_SYMBOL 64
+DEBUG_SYMBOL 37
+
sfx_skillup 1
sfx_magic_generic 2
sfx_magic_life 3
@@ -362,6 +339,7 @@ FX_MAGIC_BLUE_TELEPORT 41
FX_MAGIC_DARK_EXPLOSION 42
FX_PUMPKIN_EXPLOSION 43
FX_GETITEM 44
+FX_HUG 49
FX_MAGIC_SHIELD_ENDS 111
FX_ELECTRICITY_RED 114
FX_ELECTRICITY_BLUE 115
@@ -426,11 +404,12 @@ SKILL_RESIST_POISON 353
SKILL_ASTRAL_SOUL 354
SKILL_RAGING 355
-// Magic Skills
-SKILL_MAGIC 340
-SKILL_MAGIC_LIFE 341
-SKILL_MAGIC_WAR 342
-SKILL_MAGIC_TRANSMUTE 343
-SKILL_MAGIC_NATURE 344
-SKILL_MAGIC_ASTRAL 345
-SKILL_MAGIC_DARK 346
+// GM groups
+G_PLAYER 0
+G_BOT 1
+G_TESTER 20
+G_DEV 40
+G_EVENT 50
+G_GM 60
+G_ADMIN 80
+G_SYSOP 99
diff --git a/world/map/db/params.txt b/world/map/db/params.txt
new file mode 100644
index 00000000..4d905522
--- /dev/null
+++ b/world/map/db/params.txt
@@ -0,0 +1,51 @@
+// Params usable in scripts
+// see SP enum in clif.t.hpp
+
+// TODO finish that list and add comments
+// TODO refactor: make the names match their SP:: counterpart <== halfway done
+
+BASEEXP 1 1
+JOBEXP 2 1
+Hp 5 1
+MaxHp 6 1
+Sp 7 1
+MaxSp 8 1
+STATUSPOINT 9 1
+BaseLevel 11 1
+SKILLPOINT 12 1
+Str 13 1
+Agi 14 1
+Vit 15 1
+Int 16 1
+Dex 17 1
+Luk 18 1
+Class 19 1
+Zeny 20 1
+Sex 21 1
+NEXTBASEEXP 22 1
+NEXTJOBEXP 23 1
+Weight 24 1
+MaxWeight 25 1
+ATK1 41 1
+ATK2 42 1
+MATK1 43 1
+MATK2 44 1
+DEF1 45 1
+DEF2 46 1
+MDEF1 47 1
+MDEF2 48 1
+HIT 49 1
+FLEE1 50 1
+FLEE2 51 1
+CRITICAL 52 1
+JOBLEVEL 55 1
+PARTNER 57 1
+GM 500 1
+ATTACKRANGE 1000 1
+BASE_ATK 1014 1
+POS_X 1074 1
+POS_Y 1075 1
+PVP_CHANNEL 1076 1
+BL_ID 1077 1
+BL_TYPE 1078 1
+CHAR_ID 1079 1
diff --git a/world/map/npc/001-1/ched.txt b/world/map/npc/001-1/ched.txt
index ddfddd95..dee6cb77 100644
--- a/world/map/npc/001-1/ched.txt
+++ b/world/map/npc/001-1/ched.txt
@@ -15,9 +15,9 @@ L_Next:
mes "[Ched]";
mes "\"Well, I don't remember what it's called... I took it out of 'Timbleweed's Advanced Transmutations,' but it seems awfully hard to cast.\"";
next;
- mes "\"If you want to try it, the invocation is '" + getspellinvocation("merge-concentration-potions") + ".' I just can't get the hang of it though.\"";
+ mes "\"If you want to try it, the invocation is '" + ("merge-concentration-potions") + ".' I just can't get the hang of it though.\"";
next;
- mes "\"Maybe I should go back to practicing '" + getspellinvocation("detect-magic") + "' until I can cast it properly.\" %%6";
+ mes "\"Maybe I should go back to practicing '" + ("detect-magic") + "' until I can cast it properly.\" %%6";
goto L_Done;
L_Done:
diff --git a/world/map/npc/001-1/children.txt b/world/map/npc/001-1/children.txt
index 5ad738a9..83718566 100644
--- a/world/map/npc/001-1/children.txt
+++ b/world/map/npc/001-1/children.txt
@@ -78,7 +78,7 @@ L_keepword:
L_giveword:
mes "[Aisha]";
mes "Aisha looks around as she leans in and hushes you to silence. After a few seconds, she whispers to you:";
- mes "\"I like you, so I'll tell you the bad word. But you can't tell anyone else about it! The bad word is '" + getspellinvocation("aggravate") + ".'\"";
+ mes "\"I like you, so I'll tell you the bad word. But you can't tell anyone else about it! The bad word is '" + get(.invocation$, "spell-aggravate") + ".'\"";
next;
mes "[Aisha]";
diff --git a/world/map/npc/001-1/guards.txt b/world/map/npc/001-1/guards.txt
index 0167510e..df25a13e 100644
--- a/world/map/npc/001-1/guards.txt
+++ b/world/map/npc/001-1/guards.txt
@@ -91,6 +91,6 @@ L_message:
mes "[Ryan the Town Guard]";
mes "\" Watch out for Black Scorpions. They are extremely dangerous!\"";
next;
- mes "\"Whenever one approaches the town gate, Ekinu has me run around shouting '" + getspellinvocation("aggravate") + ".' Somehow, this distracts it so Ekinu can kill it.\"";
+ mes "\"Whenever one approaches the town gate, Ekinu has me run around shouting '" + $@SPELL_AGGRAVATE$ + ".' Somehow, this distracts it so Ekinu can kill it.\"";
close;
}
diff --git a/world/map/npc/001-2/government_building.txt b/world/map/npc/001-2/government_building.txt
index 51b43a8c..03c3eaf7 100644
--- a/world/map/npc/001-2/government_building.txt
+++ b/world/map/npc/001-2/government_building.txt
@@ -6,7 +6,7 @@
mes "[Estard]";
mes "\"Hello. What can I do for you?\"";
next;
- if (getpartnerid2())
+ if (PARTNER)
goto L_main_married;
menu
@@ -35,7 +35,7 @@ L_marry_do:
callsub S_give_rings;
mes "";
mes "[Estard]";
- mes "\"Here are your rings. In order to marry each other, you both must stand within one of the designated areas (like that small rug over there in the corner), wear your rings, and say 'marry (your partner's name).'\"";
+ mes "\"Here are your rings. In order to marry each other, you both must stand within one of the designated areas (like that small rug over there in the corner), wear your rings, and say '#marry (your partner's name).'\"";
close;
L_marry_too_young:
@@ -93,8 +93,8 @@ L_do_divorce:
if (Zeny < @divorce_cost)
goto L_not_enough_money;
- if (divorce())
- goto L_divorce_done;
+ set PARTNER, 0, PARTNER; // divorce the partner first, which will also divorce the rid if succesful
+ if (PARTNER < 1) goto L_divorce_done;
mes "";
mes "[Estard]";
diff --git a/world/map/npc/001-2/pauline.txt b/world/map/npc/001-2/pauline.txt
index 4fbd5a5f..93608a10 100644
--- a/world/map/npc/001-2/pauline.txt
+++ b/world/map/npc/001-2/pauline.txt
@@ -92,7 +92,7 @@ L_Spells:
L_Next1:
mes "[Pauline]";
mes "\"Well I could only read the invocations. So I don't exactly know what kind of ingredients you are going to need.\"";
- mes "\"The first one for the mouboo was " + getspellinvocation("summon-mouboo") + " and the one for the pinkie was " + getspellinvocation("summon-pinkie") +".\"";
+ mes "\"The first one for the mouboo was " + ("summon-mouboo") + " and the one for the pinkie was " + ("summon-pinkie") +".\"";
next;
mes "\"For the pinkie spell my suggestion is to try similar ingredients to the other Astral spells. Try a root and some item typical for pinkies.\"";
mes "\"The mouboo spell might be more complicated. From what I could translate, one of the spell components is crafted by magic.\"";
@@ -157,7 +157,7 @@ L_Next4:
goto L_DidNotWorkMouboo;
L_DidNotWorkMouboo:
- mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + getspellinvocation("summon-mouboo") + ".";
+ mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + ("summon-mouboo") + ".";
mes "Nothing happens.";
mes "[Pauline]";
mes "\"It seems you did not tell me the correct ingredients. Come back when you find the correct ones.\"";
@@ -174,7 +174,7 @@ L_Pass2Mouboo:
goto L_DidNotWorkMouboo;
L_TrySpellMouboo:
- mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + getspellinvocation("summon-mouboo") + ".";
+ mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + ("summon-mouboo") + ".";
monster "001-1", 55,68, "Good", 1028, 1;
mes "[Pauline]";
mes "\"It worked!\"";
@@ -220,7 +220,7 @@ L_Next5:
goto L_DidNotWorkPinkie;
L_DidNotWorkPinkie:
- mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + getspellinvocation("summon-pinkie") + ".";
+ mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + ("summon-pinkie") + ".";
mes "Nothing happens.";
mes "[Pauline]";
mes "\"It seems you did not tell me the correct ingredients. Come back when you find the correct ones.\"";
@@ -237,7 +237,7 @@ L_Pass2Pinkie:
goto L_DidNotWorkPinkie;
L_TrySpellPinkie:
- mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + getspellinvocation("summon-pinkie") + ".";
+ mes "The Witch takes " + @pauline_ingredient1$ + " and " + @pauline_ingredient2$ + " and puts them together calling " + ("summon-pinkie") + ".";
monster "001-1", 54,68, "Good", 1018, 1;
mes "[Pauline]";
mes "\"It worked!\"";
diff --git a/world/map/npc/001-2/tondar.txt b/world/map/npc/001-2/tondar.txt
index ba4c0fff..d7fd3531 100644
--- a/world/map/npc/001-2/tondar.txt
+++ b/world/map/npc/001-2/tondar.txt
@@ -41,7 +41,7 @@ L_askspell:
L_spell:
mes "[Tondar]";
- mes "\"Well, all right; this one can't do much harm. Press your hands together and say `" + getspellinvocation("ask-magic-exp") + "'.\"";
+ mes "\"Well, all right; this one can't do much harm. Press your hands together and say `" + get(.invocation$, "spell-experience") + "'.\"";
mes "\"This will release a steady flow of magic within you. Focus and try to control it; it is a good meditative practice.\"";
close;
diff --git a/world/map/npc/001-2/wizards.txt b/world/map/npc/001-2/wizards.txt
index 37efa8bd..ef538489 100644
--- a/world/map/npc/001-2/wizards.txt
+++ b/world/map/npc/001-2/wizards.txt
@@ -1,90 +1,25 @@
// Council of Ruling Wizards Room
-// manaseed
-001-2,104,19,0|script|Desert Mana Seed#_M|166
+-|script|Magic Council|32767
{
- mes "Strangely, you feel nothing – as if its membrane is closed to you.";
+ explode .@n, strnpcinfo(0), "#";
+ if (.@n[1] == 9) mes "The arch wizard seems to be busy.";
+ elif (.@n[1]) mes "The wizard seems to ignore you.";
+ else mes "Strangely, you feel nothing – as if its membrane is closed to you.";
next;
mes "Perhaps you should come back later.";
close;
-}
-
-//
-001-2,99,22,0|script|Wizard#1|355
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,92,24,0|script|Wizard#2|356
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,92,30,0|script|Wizard#3|357
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,99,32,0|script|Wizard#4|358
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,110,22,0|script|Wizard#5|359
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,117,24,0|script|Wizard#6|360
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-
-//
-001-2,117,30,0|script|Wizard#7|361
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-//
-001-2,110,32,0|script|Wizard#8|362
-{
- mes "The wizard seems to ignore you.";
- next;
- mes "Perhaps you should come back later.";
- close;
-}
-//
-001-2,104,27,0|script|Arch-Wizard#9|354
-{
- mes "The arch wizard seems to be busy.";
- next;
- mes "Perhaps you should come back later.";
- close;
+OnInit:
+ set .@void, puppet("001-2", 104, 19, "Desert Mana Seed#_M", 166);
+ set .@void, puppet("001-2", 99, 22, "Wizard#1", 355);
+ set .@void, puppet("001-2", 92, 24, "Wizard#2", 356);
+ set .@void, puppet("001-2", 92, 30, "Wizard#3", 357);
+ set .@void, puppet("001-2", 99, 32, "Wizard#4", 358);
+ set .@void, puppet("001-2", 110, 22, "Wizard#5", 359);
+ set .@void, puppet("001-2", 117, 24, "Wizard#6", 360);
+ set .@void, puppet("001-2", 117, 30, "Wizard#7", 361);
+ set .@void, puppet("001-2", 110, 32, "Wizard#8", 362);
+ set .@void, puppet("001-2", 104, 27, "Arch-Wizard#9", 354);
+ end;
}
diff --git a/world/map/npc/002-1/elanore.txt b/world/map/npc/002-1/elanore.txt
index ea3b78bf..fbc8f3c0 100644
--- a/world/map/npc/002-1/elanore.txt
+++ b/world/map/npc/002-1/elanore.txt
@@ -233,7 +233,7 @@ L_MakeSelf:
goto L_MakeSelf_yes;
L_MakeSelf_yes:
- mes "\"Oh, but of course! You are powerful enough to make your own lifestones, using the enchantment '" + getspellinvocation("enchant-lifestone") + "'. This will consume a bug leg or a maggot slime or one of each of the four healing herbs, though.\"";
+ mes "\"Oh, but of course! You are powerful enough to make your own lifestones, using the enchantment '" + ("enchant-lifestone") + "'. This will consume a bug leg or a maggot slime or one of each of the four healing herbs, though.\"";
goto L_Close;
L_MakeSelf_no:
@@ -265,15 +265,15 @@ L_T_Initial:
next;
mes "[Elanore the Healer]";
mes "\"To heal someone, first locate the injury. As a beginner, you have to touch the wound; with practice, it will be enough to think about it. Hold the lifestone in one hand, touching the wound with the other.\"";
- mes "\"Then say, '" + getspellinvocation("lesser-heal") + "', followed by the name of the one you wish to heal.\"";
+ mes "\"Then say, '" + ("lesser-heal") + "', followed by the name of the one you wish to heal.\"";
next;
mes "[Elanore the Healer]";
mes "\"You might want to write that down, actually. In fact, you might want to make sure to keep notes of all spells you hear, for you never know if you will hear them again!\"";
- mes "\"The invocation was '" + getspellinvocation("lesser-heal") + "'.\"";
+ mes "\"The invocation was '" + ("lesser-heal") + "'.\"";
next;
mes "[Elanore the Healer]";
mes "\"This will only cure cuts and bruises, though, and it will take some time to take effect. It will be useless to mend broken bones or more severe injuries!\"";
- mes "\"To heal yourself, it's enough to just say '" + getspellinvocation("lesser-heal") + "' by itself.\"";
+ mes "\"To heal yourself, it's enough to just say '" + ("lesser-heal") + "' by itself.\"";
next;
mes "[Elanore the Healer]";
mes "\"Let me give you a lifestone to get started with.\"";
@@ -344,7 +344,7 @@ L_T_ChkAdvToLOH:
mes "\"I will now teach you how to heal by laying on your hands. The technique is similar to the spell I taught you at the beginning, but this time you transfer your own health instead of drawing health from a lifestone.\"";
next;
mes "[Elanore the Healer]";
- mes "\"First, lay your hand on the person you wish to heal. You needn't touch the injury itself, though you have to touch the skin until you are a little more experienced. Then, medidate on the word '" + getspellinvocation("lay-on-hands") + "'\"";
+ mes "\"First, lay your hand on the person you wish to heal. You needn't touch the injury itself, though you have to touch the skin until you are a little more experienced. Then, medidate on the word '" + ("lay-on-hands") + "'\"";
next;
mes "[Elanore the Healer]";
mes "\"This will let your own life force flow into the person you are healing. If you are badly injured yourself, you will not be able to do this.\"";
@@ -500,11 +500,11 @@ L_T_CurePosion:
next;
mes "[Elanore the Healer]";
mes "\"If you would like to cure someone who is poisoned, first rub a Gamboge leaf between your hands. Your hands must be covered in Gamboge liquid for this to work.\"";
- mes "\"Speak the invocation, `" + getspellinvocation("cure-poison") + "'.\"";
+ mes "\"Speak the invocation, `" + ("cure-poison") + "'.\"";
mes "\"Next, you either touch the poisoned person with your hands, or speak their name. You have to be close for this to work, though.\"";
next;
mes "[Elanore the Healer]";
- mes "\"Once again, the invocation is `" + getspellinvocation("cure-poison") + "'.\"";
+ mes "\"Once again, the invocation is `" + ("cure-poison") + "'.\"";
mes "\"Come back again soon; there is another spell I would like to teach you.\"";
next;
set @Q_status, @STATUS_LEARNED_CURE_POISON;
diff --git a/world/map/npc/006-1/spirit.txt b/world/map/npc/006-1/spirit.txt
index 8c7155fa..9a839a81 100644
--- a/world/map/npc/006-1/spirit.txt
+++ b/world/map/npc/006-1/spirit.txt
@@ -178,7 +178,7 @@ L_Next5:
mes "\"Kekeke... excellent! Yes, here goes your first spell, the flying backpack! If you are overloaded, it will take the load off your shoulders.\"";
next;
mes "[Earth Spirit]";
- mes "\"Take a cocoon, living or dead, and suffuse it in magic. Whisper '" + getspellinvocation("flying-backpack") + "', and feel it float!\"";
+ mes "\"Take a cocoon, living or dead, and suffuse it in magic. Whisper '" + ("flying-backpack") + "', and feel it float!\"";
goto L_Q_magic_finish;
L_Q_magic_3:
@@ -196,7 +196,7 @@ L_Next6:
mes "\"Yeees, good! This one is a protection spell, making your skin harder. You need a hard spike for it, though. Hold that spike in your hands, and focus on it.\"";
next;
mes "[Earth Spirit]";
- mes "\"Next, say '" + getspellinvocation("protect") + "', and feel your skin grow rigid! Very useful against stings and stabs and pokes and pricks and that sort of stuff.\"";
+ mes "\"Next, say '" + ("protect") + "', and feel your skin grow rigid! Very useful against stings and stabs and pokes and pricks and that sort of stuff.\"";
goto L_Q_magic_finish;
L_Q_magic_4:
diff --git a/world/map/npc/006-1/tree.txt b/world/map/npc/006-1/tree.txt
index 6740312e..57209d24 100644
--- a/world/map/npc/006-1/tree.txt
+++ b/world/map/npc/006-1/tree.txt
@@ -160,9 +160,3 @@ L_Close:
callfunc "QuestTreeTouch";
close;
}
-
-006-1,83,59,0|script|#DruidTree1#_M|400
-{
- callfunc "QuestTreeTouch";
- close;
-}
diff --git a/world/map/npc/007-2/witch.txt b/world/map/npc/007-2/witch.txt
index 557b5f62..f5fcda32 100644
--- a/world/map/npc/007-2/witch.txt
+++ b/world/map/npc/007-2/witch.txt
@@ -639,10 +639,10 @@ OnTimer34000:
end;
// Trigger 4 areatimers to show the teleport spell
// This is better looking than a basic areawarp
- areatimer "007-2", 0, 0, 57, 55, 3000, "Valia::OnWarpHero";
- areatimer "007-2", 0, 0, 57, 55, 3500, "Valia::OnWarpHelper1";
- areatimer "007-2", 0, 0, 57, 55, 4000, "Valia::OnWarpHelper2";
- areatimer "007-2", 0, 0, 57, 55, 4500, "Valia::OnWarpHelper3";
+ areatimer 0, "007-2", 0, 0, 57, 55, 3000, "Valia::OnWarpHero";
+ areatimer 0, "007-2", 0, 0, 57, 55, 3500, "Valia::OnWarpHelper1";
+ areatimer 0, "007-2", 0, 0, 57, 55, 4000, "Valia::OnWarpHelper2";
+ areatimer 0, "007-2", 0, 0, 57, 55, 4500, "Valia::OnWarpHelper3";
npctalk strnpcinfo(0), "Spiralis Major!";
misceffect FX_BLUE_MAGIC_CAST;
end;
diff --git a/world/map/npc/008-1/hinnak.txt b/world/map/npc/008-1/hinnak.txt
index c2360141..d3828d74 100644
--- a/world/map/npc/008-1/hinnak.txt
+++ b/world/map/npc/008-1/hinnak.txt
@@ -217,7 +217,7 @@ L_Sagatha_scary:
L_Sagatha_word:
mes "[Farmer Hinnak]";
- mes "\"Oh, I can't be sure... but something like '" + getspellinvocation("summon-maggots") + "', I think.\"";
+ mes "\"Oh, I can't be sure... but something like '" + ("summon-maggots") + "', I think.\"";
goto L_Close;
L_NoBeer:
diff --git a/world/map/npc/009-2/misc.txt b/world/map/npc/009-2/misc.txt
index b28d43b5..139033ec 100644
--- a/world/map/npc/009-2/misc.txt
+++ b/world/map/npc/009-2/misc.txt
@@ -39,7 +39,7 @@ L_magic:
mes "The page after that is once again hastily written, with many crossed out words and sections and side remarks such as 'it almost worked' or 'it worked fine yesterday.'";
next;
mes "[Bookshelf]";
- mes "The last word on that page is '" + getspellinvocation("make-iron-powder") + ",' and it's underlined twice with a comment next to it saying 'finally got it right.'";
+ mes "The last word on that page is '" + ("make-iron-powder") + ",' and it's underlined twice with a comment next to it saying 'finally got it right.'";
next;
mes "[Bookshelf]";
mes "Unfortunately, you can't make out what the transmutation is for or even whether it requires any materials...";
diff --git a/world/map/npc/009-2/wyara.txt b/world/map/npc/009-2/wyara.txt
index ba33d29f..d0bffbea 100644
--- a/world/map/npc/009-2/wyara.txt
+++ b/world/map/npc/009-2/wyara.txt
@@ -242,7 +242,7 @@ L_M_spell:
L_M_spell3:
mes "[Wyara the Witch]";
- mes "\"Now that you know the basics of nature magic, here is one of my favourites: '" + getspellinvocation("rain") + "' will summon rain, whereever you are standing. It will consume a bottle of water, though.\"";
+ mes "\"Now that you know the basics of nature magic, here is one of my favourites: '" + ("rain") + "' will summon rain, whereever you are standing. It will consume a bottle of water, though.\"";
if (getskilllv(SKILL_MAGIC) < 2)
mes "\"You are not powerful enough to use it yet, though; you will first have to absorb more magic from the mana seed.\"";
next;
@@ -250,14 +250,14 @@ L_M_spell3:
L_M_spell2:
mes "[Wyara the Witch]";
- mes "\"Here is another useful one: '" + getspellinvocation("detect-players") + "'. It will tell you the names of everyone nearby, but beware that there are ways to protect against it.\"";
+ mes "\"Here is another useful one: '" + ("detect-players") + "'. It will tell you the names of everyone nearby, but beware that there are ways to protect against it.\"";
if (getskilllv(SKILL_MAGIC) < 2)
mes "\"Hmm. You aren't powerful enough for this one either yet, I think.\"";
next;
if (!(getpartnerid2()))
goto L_M_main;
mes "[Wyara the Witch]";
- mes "\"Married partners can find each other even more easily. Use the '" + getspellinvocation("sense-spouse") + "' spell instead.\"";
+ mes "\"Married partners can find each other even more easily. Use the '" + ("sense-spouse") + "' spell instead.\"";
next;
goto L_M_main;
diff --git a/world/map/npc/009-3/sword.txt b/world/map/npc/009-3/sword.txt
index 91366f9e..dbb177bc 100644
--- a/world/map/npc/009-3/sword.txt
+++ b/world/map/npc/009-3/sword.txt
@@ -103,7 +103,7 @@ L_Next1:
mes "\"So thou art bound to the path of War, as am I, as is my sister...\"";
next;
mes "[Magic Sword]";
- mes "\"So be it, fellow warrior. Hear the incantation for the blade spell: '" + getspellinvocation("magic-blade") + "'\"";
+ mes "\"So be it, fellow warrior. Hear the incantation for the blade spell: '" + ("magic-blade") + "'\"";
mes "\"Hold a knife, sharp or regular, when thou speakest it.\"";
set @Q_status, @STATUS_LEARNED_MAGICBLADE;
callsub S_update_var;
@@ -152,7 +152,7 @@ L_Next3:
mes "\"The spell I shall teach thee is the hail of arrows spell. It will make arrows fall down from the heavens unto thy enemies.\"";
next;
mes "[Magic Sword]";
- mes "\"Take twenty arrows, sprinkle sulphur powder over them, and then speak '" + getspellinvocation("arrow-hail") + "'. Throw them high up in the air, and watch the hail unfold before thy feet.\"";
+ mes "\"Take twenty arrows, sprinkle sulphur powder over them, and then speak '" + get(.invocation$, "arrow-hail") + "'. Throw them high up in the air, and watch the hail unfold before thy feet.\"";
close;
L_L2_almost_done:
diff --git a/world/map/npc/009-6/brodomir.txt b/world/map/npc/009-6/brodomir.txt
index 02704447..ea73ac36 100644
--- a/world/map/npc/009-6/brodomir.txt
+++ b/world/map/npc/009-6/brodomir.txt
@@ -195,7 +195,7 @@ L_SkipItemback:
L_Check:
if (getareausers("009-5", 20, 20, 80, 80, 1) > 1)
end;
- areatimer "009-5", 20, 20, 80, 80, 0, "Brodomir::OnReward";
+ areatimer 0, "009-5", 20, 20, 80, 80, 0, "Brodomir::OnReward";
goto L_End;
OnReward:
diff --git a/world/map/npc/009-7/eventHandler.txt b/world/map/npc/009-7/eventHandler.txt
index d20fff4d..6f6419ca 100644
--- a/world/map/npc/009-7/eventHandler.txt
+++ b/world/map/npc/009-7/eventHandler.txt
@@ -40,7 +40,7 @@ OnBecomeKiller:
end;
OnCommandIntrusion:
- areatimer "009-7", $@fightclub_x1, $@fightclub_y1, $@fightclub_x2, $@fightclub_y2, 0, "#FightClubUtils::OnIntrusion"; // we can not do this directly on #handler because it already have a timer
+ areatimer 0, "009-7", $@fightclub_x1, $@fightclub_y1, $@fightclub_x2, $@fightclub_y2, 0, "#FightClubUtils::OnIntrusion"; // we can not do this directly on #handler because it already have a timer
end;
}
diff --git a/world/map/npc/009-7/rouge.txt b/world/map/npc/009-7/rouge.txt
index 7660683e..b9b8e4cd 100644
--- a/world/map/npc/009-7/rouge.txt
+++ b/world/map/npc/009-7/rouge.txt
@@ -78,13 +78,13 @@ L_Challenge:
next;
mes "[Rouge]";
mes "To challenge a player to a duel, you need to write this command:";
- mes "%%E ##a"+ getspellinvocation("duel") +" (name)##0";
+ mes "%%E ##a"+ ("duel") +" (name)##0";
next;
mes "Your opponent will have to talk to me to accept or decline your offer.";
mes "The request will expire ##2"+ @time$ +"##0 after being sent.";
next;
mes "Keep in mind that you can ignore incoming duel requests with this command:";
- mes "%%E ##a"+ getspellinvocation("dueloff") +"##0";
+ mes "%%E ##a"+ ("dueloff") +"##0";
next;
mes "To un-ignore, simply write the same command again.";
goto L_End;
diff --git a/world/map/npc/011-1/auldsbel.txt b/world/map/npc/011-1/auldsbel.txt
index 094651e9..4a57b75b 100644
--- a/world/map/npc/011-1/auldsbel.txt
+++ b/world/map/npc/011-1/auldsbel.txt
@@ -236,7 +236,7 @@ L_Sul_t_s:
mes "\"Very well, then. You have been quite helpful with my experiments, after all. As you may have noticed, the spell takes a pile of volcanic ashes. Close your hands around it, then whisper the invocation.\"";
next;
mes "[Auldsbel the Wizard]";
- mes "\"That invocation is '" + getspellinvocation("make-sulphur") + "'.\"";
+ mes "\"That invocation is '" + ("make-sulphur") + "'.\"";
next;
mes "[Auldsbel the Wizard]";
mes "\"You may find that you can transmute the powder more effectively after a while; that is perfectly natural.\"";
@@ -332,7 +332,7 @@ L_about_nature:
L_about_other_spells:
mes "[Auldsbel the Wizard]";
- mes "\"A few spells are not claimed by any particular school of magic. In practice, this means that anyone can cast them if they just have sufficient magical power. The most prominent example is the 'detect magic' spell, '" + getspellinvocation("detect-magic") + "'.\"";
+ mes "\"A few spells are not claimed by any particular school of magic. In practice, this means that anyone can cast them if they just have sufficient magical power. The most prominent example is the 'detect magic' spell, '" + ("detect-magic") + "'.\"";
next;
goto L_a_s_minimenu;
@@ -984,10 +984,10 @@ L_learn_spell:
mes "\"This spell is a simple transmutation invocation. All it takes is a clean wooden log. Hold it in your hand, focus your powers, and say the magic invocation.\"";
next;
mes "[Auldsbel the Wizard]";
- mes "\"You can turn the log into a wooden figurine by imagining the creature whose shape you want in your head and saying `" + getspellinvocation("transmute-wood-to-figurine") + ",' followed by the last syllable of the name of the creature you want to shape it into.\"";
+ mes "\"You can turn the log into a wooden figurine by imagining the creature whose shape you want in your head and saying `" + ("transmute-wood-to-figurine") + ",' followed by the last syllable of the name of the creature you want to shape it into.\"";
next;
mes "[Auldsbel the Wizard]";
- mes "\"So `" + getspellinvocation("transmute-wood-to-figurine") + " lurk' for a Skytlurk figurine, for example. If you know what a Skytlurk is, I mean, otherwise you will have a hard time imagining it. You may want to try some others instead, though.\"";
+ mes "\"So `" + ("transmute-wood-to-figurine") + " lurk' for a Skytlurk figurine, for example. If you know what a Skytlurk is, I mean, otherwise you will have a hard time imagining it. You may want to try some others instead, though.\"";
next;
mes "[Auldsbel the Wizard]";
mes "\"Oh... and it has to be the old Tritan name. Most creatures nowadays have very different names, but some old Tritan names have survived. Just try some, until you find one that fits.\"";
@@ -1001,7 +1001,7 @@ L_learn_spell:
L_repeat_spell:
mes "[Auldsbel the Wizard]";
- mes "\"The invocation is `" + getspellinvocation("transmute-wood-to-figurine") + ",' followed by the last syllable of the name of the creature you want to shape the log into. So `" + getspellinvocation("transmute-wood-to-figurine") + " lurk' for a Skytlurk figurine.\"";
+ mes "\"The invocation is `" + ("transmute-wood-to-figurine") + ",' followed by the last syllable of the name of the creature you want to shape the log into. So `" + ("transmute-wood-to-figurine") + " lurk' for a Skytlurk figurine.\"";
next;
mes "[Auldsbel the Wizard]";
mes "\"But keep two things in mind: First, you must KNOW what the creature looks like – so a Skytlurk probably won't work – and second, you must use the old Tritan name of it. `Fluffy' and `Scorpion' are modern names, so those won't work, you should try some others.\"";
@@ -1092,7 +1092,7 @@ L_Next9:
mes "[1000 experience points]";
next;
mes "[Auldsbel the Wizard]";
- mes "\"Now, listen carefully: to make a short tank top out of three pieces of cloth, you must use the invocation '" + getspellinvocation("make-short-tanktop") + "'.\"";
+ mes "\"Now, listen carefully: to make a short tank top out of three pieces of cloth, you must use the invocation '" + ("make-short-tanktop") + "'.\"";
next;
mes "[Auldsbel the Wizard]";
mes "\"But be careful; transmutations can go wrong, and that can injure you. When you have more overall spellcasting practice, come back to me.\"";
@@ -1131,7 +1131,7 @@ L_Next10:
mes "[1000 experience points]";
next;
mes "[Auldsbel the Wizard]";
- mes "\"The next spell I have will make a normal tank top out of four pieces of cloth. The invocation is '" + getspellinvocation("make-tanktop") + "', make sure to write this down.\"";
+ mes "\"The next spell I have will make a normal tank top out of four pieces of cloth. The invocation is '" + ("make-tanktop") + "', make sure to write this down.\"";
next;
goto L_main_menu;
@@ -1161,7 +1161,7 @@ L_Next11:
mes "[1000 experience points]";
next;
mes "[Auldsbel the Wizard]";
- mes "\"To make a shirt, use the invocation '" + getspellinvocation("make-shirt") + "'. This will require five pieces of cloth.\"";
+ mes "\"To make a shirt, use the invocation '" + ("make-shirt") + "'. This will require five pieces of cloth.\"";
next;
goto L_main_menu;
@@ -1191,7 +1191,7 @@ L_Next12:
mes "[1000 experience points]";
next;
mes "[Auldsbel the Wizard]";
- mes "\"This spell makes arrows out of a single wooden log. Its invocation is '" + getspellinvocation("make-arrows") + "'.\"";
+ mes "\"This spell makes arrows out of a single wooden log. Its invocation is '" + ("make-arrows") + "'.\"";
next;
goto L_main_menu;
@@ -1205,7 +1205,7 @@ L_stu_3:
L_stu_3_repeat:
mes "[Auldsbel the Wizard]";
- mes "\"This one has the invocation `" + getspellinvocation("make-concentration-potion") + "'. Put two cobalt leaves and two pink flower petals into a bottle of water, hold it up, and speak that phrase.\"";
+ mes "\"This one has the invocation `" + ("make-concentration-potion") + "'. Put two cobalt leaves and two pink flower petals into a bottle of water, hold it up, and speak that phrase.\"";
next;
mes "[Auldsbel the Wizard]";
mes "\"It is a tricky spell, but if it works out, you will transform the bottle into a concentration potion.\"";
diff --git a/world/map/npc/012-3/mana-seed.txt b/world/map/npc/012-3/mana-seed.txt
index bb479c2b..35d6ea52 100644
--- a/world/map/npc/012-3/mana-seed.txt
+++ b/world/map/npc/012-3/mana-seed.txt
@@ -37,7 +37,7 @@
"You may only be children, but you recognize that it is this man only who can save the world. As the walls rush towards you to crush your small group, you exchange a glance with your twin sister – there is no doubt what you must do...",
"The sacred place is surrounded by nothingness; were it not for your magic, you would have no hope of returning. The old and young man stands nearby; he has been waiting for you, for centuries. He has all the time in the world, after all...",
"Nothing remains behind. The underground castle is empty now, its chambers plundered, its throne destroyed. Shivering, you climb down the stairs, towards the wailing of the underworld that is waiting beneath...",
- "You feel soft, fluffy fur brushing against your skin and are filled with happiness. Somehow, the word `" + getspellinvocation("happy-curse") + "' comes to mind...";
+ "You feel soft, fluffy fur brushing against your skin and are filled with happiness. Somehow, the word `" + ("happy-curse") + "' comes to mind...";
set @max_magic, 2;
diff --git a/world/map/npc/013-1/sagatha.txt b/world/map/npc/013-1/sagatha.txt
index 558e9b70..84336eef 100644
--- a/world/map/npc/013-1/sagatha.txt
+++ b/world/map/npc/013-1/sagatha.txt
@@ -267,7 +267,7 @@ L_teach_N14:
mes "\"Some forest creatures sometimes overgrow their fur or hide. That makes them uncomfortable.\"";
next;
mes "[Sagatha the Witch]";
- mes "\"You can help them with shearing magic. Press your hands together and say '" + getspellinvocation("shear") + "'. Then touch them with your hands, and brush off any excess.\"";
+ mes "\"You can help them with shearing magic. Press your hands together and say '" + ("shear") + "'. Then touch them with your hands, and brush off any excess.\"";
next;
mes "[Sagatha the Witch]";
mes "\"The spell is strong, so you only need to do this once. Be careful not to cut them. Some things they shed are useful. Often they will leave them to you as a thank-you.\"";
@@ -280,7 +280,7 @@ L_teach_N10:
mes "\"Next, a nature spell. Take a cocoon shell. Hold it in your hand. Feel its lightness.\"";
next;
mes "[Sagatha the Witch]";
- mes "\"Now whisper '" + getspellinvocation("flying-backpack") + "', and if your backpack was pressing on you you should no longer feel it now.\"";
+ mes "\"Now whisper '" + ("flying-backpack") + "', and if your backpack was pressing on you you should no longer feel it now.\"";
goto L_practice;
L_teach_A10:
@@ -290,14 +290,14 @@ L_teach_A10:
mes "\"To protect against others' magic, take a small mushroom from a shady place. Mushrooms draw things out of the earth. Rub your mushroom into pieces between your hands.\"";
next;
mes "[Sagatha the Witch]";
- mes "\"Then say '" + getspellinvocation("barrier") + "' and let the mushroom's power take over.\"";
+ mes "\"Then say '" + ("barrier") + "' and let the mushroom's power take over.\"";
goto L_practice;
L_teach_A11:
if (@mexp < 200)
goto L_teach_noexp;
mes "[Sagatha the Witch]";
- mes "\"If you must fight, call allies. You can call spiky mushrooms out of the ground with a mushroom spike and a root. Hold up the spike and call out to them: '" + getspellinvocation("summon-spiky-mushrooms") + "'. Then press the root to the ground.\"";
+ mes "\"If you must fight, call allies. You can call spiky mushrooms out of the ground with a mushroom spike and a root. Hold up the spike and call out to them: '" + ("summon-spiky-mushrooms") + "'. Then press the root to the ground.\"";
next;
mes "[Sagatha the Witch]";
mes "\"Spiky mushrooms often grow too many spikes, so you can shear the spikes off of some.\"";
@@ -308,17 +308,17 @@ L_teach_A12:
if (@mexp < 220)
goto L_teach_noexp;
mes "[Sagatha the Witch]";
- mes "\"You can call fluffies, too. But for them you must call out '" + getspellinvocation("summon-fluffies") + "' instead, with white fluffy fur instead of a spike. And don't forget the root.\"";
+ mes "\"You can call fluffies, too. But for them you must call out '" + ("summon-fluffies") + "' instead, with white fluffy fur instead of a spike. And don't forget the root.\"";
goto L_practice;
L_teach_N11:
if (@mexp < 250)
goto L_teach_noexp;
mes "[Sagatha the Witch]";
- mes "\"You can harden your skin with a hard spike. Hold it in your hands and speak '" + getspellinvocation("protect") + "', then draw its hardness into your skin.\"";
+ mes "\"You can harden your skin with a hard spike. Hold it in your hands and speak '" + ("protect") + "', then draw its hardness into your skin.\"";
next;
mes "[Sagatha the Witch]";
- mes "\"Or call it into someone else's skin, by saying that someone's name right after the '" + getspellinvocation("protect") + "'.\"";
+ mes "\"Or call it into someone else's skin, by saying that someone's name right after the '" + ("protect") + "'.\"";
goto L_practice;
L_teach_noexp:
diff --git a/world/map/npc/013-2/wizard.txt b/world/map/npc/013-2/wizard.txt
index ced2865b..cf8598b0 100644
--- a/world/map/npc/013-2/wizard.txt
+++ b/world/map/npc/013-2/wizard.txt
@@ -75,7 +75,7 @@ L_TeachSpell:
mes "\"This one may not seem too powerful, but it can be quite handy; it's the 'hide' spell. It will shield you from some forms of detection magic.\"";
next;
mes "[Old Wizard]";
- mes "\"Put a piece of cotton cloth on your head, and speak out '" + getspellinvocation("hide") + "', loudly and clearly. The protection lasts quite long, but you may have to renew it on occasion.\"";
+ mes "\"Put a piece of cotton cloth on your head, and speak out '" + ("hide") + "', loudly and clearly. The protection lasts quite long, but you may have to renew it on occasion.\"";
next;
mes "[Old Wizard]";
mes "\"You can also cast it on others, of course. Just speak their name after you pronounce the invocation.\"";
diff --git a/world/map/npc/014-1/wedding-officiator.txt b/world/map/npc/014-1/wedding-officiator.txt
index fc237082..dfdab00b 100644
--- a/world/map/npc/014-1/wedding-officiator.txt
+++ b/world/map/npc/014-1/wedding-officiator.txt
@@ -9,7 +9,7 @@
goto L_main;
L_main:
- if (getpartnerid2())
+ if (PARTNER)
goto L_main_married;
menu
@@ -35,10 +35,10 @@ L_explain_marriage:
mes "\"Both you and your partner must be at least " + WEDDING_MIN_LEVEL + " levels of age, though; the law is very firm on that. But if all of that works out, I will give you two wedding rings for the ceremony.\"";
next;
mes "[Wedding Officiator]";
- mes "\"To complete the marriage, each of you has to put on one of these rings, and you have to stand next to each other in the southern part of this park. Then one of you says `marry' and then the other person's name.\"";
+ mes "\"To complete the marriage, each of you has to put on one of these rings, and you have to stand next to each other in the southern part of this park. Then one of you says `#marry' and then the other person's name.\"";
next;
mes "[Wedding Officiator]";
- mes "\"So if you would want to marry me, for example, you would say `marry Wendy'. Just like that. Your partner then has to decide whether he or she wants that. And if you both agree, then you're married!\"";
+ mes "\"So if you would want to marry me, for example, you would say `#marry Wendy'. Just like that. Your partner then has to decide whether he or she wants that. And if you both agree, then you're married!\"";
mes "She again smiles that broad smile of hers.";
next;
goto L_main;
@@ -135,7 +135,7 @@ L_too_poor:
L_main_married:
mes "[Wedding Officiator]";
- mes "\"I hope that you and your partner are doing well?\"";
+ mes "\"I hope that you and "+ strcharinfo(0, get(BL_ID, PARTNER)) +" are doing well?\"";
next;
menu
"We are very happy, thanks for asking!", L_farewell,
@@ -219,8 +219,8 @@ L_divorce_nomoney:
L_do_divorce:
if (Zeny < @divorce_cost)
goto L_divorce_nomoney;
- if (divorce())
- goto L_DidDivorce;
+ set PARTNER, 0, PARTNER; // divorce the partner first, which will also divorce the rid if succesful
+ if (PARTNER < 1) goto L_DidDivorce;
mes "[Wedding Officiator]";
mes "The officiator searches through her records for your partner.";
diff --git a/world/map/npc/015-1/sword.txt b/world/map/npc/015-1/sword.txt
index 239de752..90c56283 100644
--- a/world/map/npc/015-1/sword.txt
+++ b/world/map/npc/015-1/sword.txt
@@ -109,7 +109,7 @@ L_Initial_ok:
mes "\"Oh, my apologies – that was a little overly dramatic. But I do not get to talk to thy kin anymore all that often.\"";
next;
mes "[Mystic Sword]";
- mes "\"For the flare dart spell throw a handful of sulphur powder up into the air, and say, '" + getspellinvocation("flare-dart") + "'.\"";
+ mes "\"For the flare dart spell throw a handful of sulphur powder up into the air, and say, '" + ("flare-dart") + "'.\"";
set @Q_status, @STATUS_LEARNED_FLAREDART;
callsub S_update_var;
next;
@@ -257,7 +257,7 @@ L_Next3:
callsub S_update_var;
next;
mes "[Mystic Sword]";
- mes "\"Speak '" + getspellinvocation("magic-knuckles") + "' and take a glass of beer and drink it, without ever taking it off thy lips. This will harden and enchant thy fists, turning them into powerful weapons.\"";
+ mes "\"Speak '" + ("magic-knuckles") + "' and take a glass of beer and drink it, without ever taking it off thy lips. This will harden and enchant thy fists, turning them into powerful weapons.\"";
close;
L_L2_almost_done:
@@ -297,7 +297,7 @@ L_Next4:
callsub S_update_var;
next;
mes "[Mystic Sword]";
- mes "\"This powder thou shalst need to cast the lightning spell. Throw it up into the air and shout '" + getspellinvocation("lightning-strike") + "', and smite thine enemies with lightning.\"";
+ mes "\"This powder thou shalst need to cast the lightning spell. Throw it up into the air and shout '" + ("lightning-strike") + "', and smite thine enemies with lightning.\"";
next;
goto L_Farewell;
diff --git a/world/map/npc/017-4/waric.txt b/world/map/npc/017-4/waric.txt
index f98cb0d0..11f836b6 100644
--- a/world/map/npc/017-4/waric.txt
+++ b/world/map/npc/017-4/waric.txt
@@ -234,7 +234,7 @@ L_Mushroom:
mes "\"Now that you are a student of mine, I will teach you some spells.\"";
next;
mes "\"We will start with an easy one. I will teach you how to summon a wicked mushroom.\"";
- mes "\"The spell consumes a Small Mushroom and a Dark Crystal. Shove the Dark Crystal into the Small Mushroom and yell " + getspellinvocation("summon-wickedmushroom") +".\"";
+ mes "\"The spell consumes a Small Mushroom and a Dark Crystal. Shove the Dark Crystal into the Small Mushroom and yell " + ("summon-wickedmushroom") +".\"";
next;
mes "\"A wicked mushroom will appear to fight for you.\"";
set OrumQuest, 37;
@@ -254,7 +254,7 @@ L_Next4:
next;
mes "\"You have to use two roots for this spell. First you have to take one root and break off all the root hair. Shape it into a stick, if you will. Then put it on top of the other root and form an arrow-like structure.\"";
next;
- mes "\"Once this is done you have to throw it in the air and scream " + getspellinvocation("toxic-dart") + " and the two roots will turn into toxic darts, a projectile you can throw.\"";
+ mes "\"Once this is done you have to throw it in the air and scream " + ("toxic-dart") + " and the two roots will turn into toxic darts, a projectile you can throw.\"";
next;
mes "\"If you want to learn more, come back later.\"";
set OrumQuest, 38;
@@ -312,7 +312,7 @@ L_SnakesSpell:
L_Next7:
mes "[Waric]";
- mes "\"I said " + getspellinvocation("summon-snakes") + ".\"";
+ mes "\"I said " + ("summon-snakes") + ".\"";
mes "\"Have fun with those spells and use them to cause hate, anger and death.\"";
set OrumQuest, 41;
goto L_Close;
@@ -341,9 +341,9 @@ L_MoreMagic:
L_Next8:
mes "[Waric]";
mes "\"Yes, of course.\"";
- mes "\"To summon the snakes use " + getspellinvocation("summon-snakes") + ".\"";
- mes "\"Say " + getspellinvocation("toxic-dart") + " to make your roots into toxic darts.\"";
- mes "\"And the first spell, to summon wicked mushrooms, is " + getspellinvocation("summon-wickedmushroom") + ".\"";
+ mes "\"To summon the snakes use " + ("summon-snakes") + ".\"";
+ mes "\"Say " + ("toxic-dart") + " to make your roots into toxic darts.\"";
+ mes "\"And the first spell, to summon wicked mushrooms, is " + ("summon-wickedmushroom") + ".\"";
next;
mes "\"Now leave. Spread chaos with the spells I have taught you!\"";
goto L_Close;
diff --git a/world/map/npc/017-9/npcs.txt b/world/map/npc/017-9/npcs.txt
index b14428c5..e5a2ec04 100644
--- a/world/map/npc/017-9/npcs.txt
+++ b/world/map/npc/017-9/npcs.txt
@@ -44,3 +44,13 @@
callfunc "SuperDebug";
end;
}
+
+-|script|Numa Spell|32767
+{
+ callfunc "SuperDebug";
+ end;
+
+OnInit:
+ registercmd "@numa", "Numa Spell";
+ end;
+}
diff --git a/world/map/npc/027-6/general_krukan.txt b/world/map/npc/027-6/general_krukan.txt
index 6b086cee..1c2ff95f 100644
--- a/world/map/npc/027-6/general_krukan.txt
+++ b/world/map/npc/027-6/general_krukan.txt
@@ -86,7 +86,7 @@ OnTimer5000:
L_Return_1:
set $@CRYPT_FIGHT1_PLAYER_COUNT, 0;
- areatimer "027-6", 0, 0, 79, 84, 10, "General Krukan::OnTick";
+ areatimer 0, "027-6", 0, 0, 79, 84, 10, "General Krukan::OnTick";
end;
L_CryptLogic:
@@ -182,7 +182,7 @@ L_CleanUpLosers:
end;
L_CleanUp:
- areatimer "027-6", 0, 0, 79, 84, 10, "General Krukan::OnReward";
+ areatimer 0, "027-6", 0, 0, 79, 84, 10, "General Krukan::OnReward";
set $@CRYPT_FIGHT1, 0;
set $@CRYPT_FIGHT1_PLAYER_COUNT, 0;
set $@CRYPT_FIGHT1_WAVE, 0;
diff --git a/world/map/npc/027-7/general_razha.txt b/world/map/npc/027-7/general_razha.txt
index e22f6392..f331d95c 100644
--- a/world/map/npc/027-7/general_razha.txt
+++ b/world/map/npc/027-7/general_razha.txt
@@ -86,7 +86,7 @@ OnTimer5000:
L_Return_1:
set $@CRYPT_FIGHT2_PLAYER_COUNT, 0;
- areatimer "027-7", 0, 0, 79, 84, 10, "General Razha::OnTick";
+ areatimer 0, "027-7", 0, 0, 79, 84, 10, "General Razha::OnTick";
end;
L_CryptLogic:
@@ -186,7 +186,7 @@ L_CleanUpLosers:
L_CleanUp:
mapannounce "027-7", "General Razha : How in all hells could that happen? I am lost forever.", 0;
mapannounce "027-4", "General Razha is defeated.", 0;
- areatimer "027-7", 0, 0, 79, 84, 10, "General Razha::OnReward";
+ areatimer 0, "027-7", 0, 0, 79, 84, 10, "General Razha::OnReward";
set $@CRYPT_FIGHT2, 0;
set $@CRYPT_FIGHT2_PLAYER_COUNT, 0;
set $@CRYPT_FIGHT2_WAVE, 0;
diff --git a/world/map/npc/027-8/general_terogan.txt b/world/map/npc/027-8/general_terogan.txt
index ca8691f0..522b1eaa 100644
--- a/world/map/npc/027-8/general_terogan.txt
+++ b/world/map/npc/027-8/general_terogan.txt
@@ -141,7 +141,7 @@ OnTimer5000:
L_Return_1:
set $@CRYPT_FIGHT3_PLAYER_COUNT, 0;
- areatimer "027-8", 0, 0, 79, 84, 10, "General Terogan#Main::OnTick";
+ areatimer 0, "027-8", 0, 0, 79, 84, 10, "General Terogan#Main::OnTick";
end;
L_CryptLogic:
@@ -249,7 +249,7 @@ L_CleanUpLosers:
L_CleanUp:
mapannounce "027-8", "General Terogan : You might have won this battle, but you will never defeat me!", 0;
- areatimer "027-8", 0, 0, 79, 84, 10, "General Terogan#Main::OnReward";
+ areatimer 0, "027-8", 0, 0, 79, 84, 10, "General Terogan#Main::OnReward";
set $@CRYPT_FIGHT3, 0;
set $@CRYPT_FIGHT3_PLAYER_COUNT, 0;
set $@CRYPT_FIGHT3_WAVE, 0;
diff --git a/world/map/npc/029-1/barrier.txt b/world/map/npc/029-1/barrier.txt
index e6c580ad..7414f78b 100644
--- a/world/map/npc/029-1/barrier.txt
+++ b/world/map/npc/029-1/barrier.txt
@@ -18,6 +18,6 @@ OnTalk:
end;
OnCommandTalk:
- areatimer "029-1", 61, 61, 69, 73, 0, "#CandorAnnouncer::OnTalk";
+ areatimer 0, "029-1", 61, 61, 69, 73, 0, "#CandorAnnouncer::OnTalk";
end;
}
diff --git a/world/map/npc/029-2/morgan.txt b/world/map/npc/029-2/morgan.txt
index 1f8f19f4..d5604f93 100644
--- a/world/map/npc/029-2/morgan.txt
+++ b/world/map/npc/029-2/morgan.txt
@@ -78,7 +78,7 @@ L_Start:
mes "\"Various wands and staffs are found throughout the land with many different strengths and weaknesses.\"";
mes "\"To use the wand you need to have it equipped and speak the incantation to let it tap into your mana.\"";
mes "\"As the power of your magic grows so will the spells you can cast.\"";
- mes "\"Lets start with a basic wand attack. " + getspellinvocation("wand") + "\"";
+ mes "\"Lets start with a basic wand attack. " + get(.invocation$, "spell-wand") + "\"";
mes "\"Equip the wand and lets try out that spell.\"";
mes "\"To cast a spell open the chat window, type the invocation and press enter.\"";
mes "\"Speak to me again once you've cast the spell.\"";
@@ -86,7 +86,7 @@ L_Start:
L_Started:
mes "[Morgan]";
- mes "\"Lets start with a basic wand attack. " + getspellinvocation("wand") + "\"";
+ mes "\"Lets start with a basic wand attack. " + get(.invocation$, "spell-wand") + "\"";
mes "\"Equip the wand and lets try out that spell.\"";
mes "\"To cast a spell open the chat window, type the invocation and press enter.\"";
mes "\"Speak to me again once you've cast the spell.\"";
@@ -95,7 +95,7 @@ L_Started:
L_CastOnce:
mes "[Morgan]";
mes "\"Ok, good job! Looks like you have good mana flow.\"";
- mes "\"Onto the next lesson. Now that you have " + getspellinvocation("wand") + " cast,\"";
+ mes "\"Onto the next lesson. Now that you have " + get(.invocation$, "spell-wand") + " cast,\"";
mes "\"Each time you attack the wand will convert a bit of you mana into a magic bolt.\"";
mes "\"After so many attacks, you will need to recast the invocation to stay attuned to the wand.\"";
mes "\"(Logging out will also cancel any spell effects currently active in-game.).\"";
@@ -106,7 +106,7 @@ L_CastOnce:
L_LearningDone:
mes "[Morgan]";
- mes "\"" + getspellinvocation("wand") + " is a basic wand attack.\"";
+ mes "\"" + get(.invocation$, "spell-wand") + " is a basic wand attack.\"";
mes "\"A Wand must be equipped to use the spell.\"";
mes "\"To cast a spell open the chat window, type the invocation and press enter.\"";
mes "\"I've taught you all I can for now. You should visit the Mana Seed north west of Hurnscald.\"";
diff --git a/world/map/npc/029-2/tanisha.txt b/world/map/npc/029-2/tanisha.txt
index 7142721e..025cc499 100644
--- a/world/map/npc/029-2/tanisha.txt
+++ b/world/map/npc/029-2/tanisha.txt
@@ -221,7 +221,7 @@ OnTimer1000:
if (getareausers("029-2", 98, 84, 106, 89) == 0)
goto L_CleanUp;
// This is needed because multiple players can be in the area at once
- areatimer "029-2", 98, 84, 106, 89, 0, "Tanisha::OnTick";
+ areatimer 0, "029-2", 98, 84, 106, 89, 0, "Tanisha::OnTick";
end;
L_CleanUp:
diff --git a/world/map/npc/029-3/parua.txt b/world/map/npc/029-3/parua.txt
index 5ebcc4d7..ef630413 100644
--- a/world/map/npc/029-3/parua.txt
+++ b/world/map/npc/029-3/parua.txt
@@ -187,7 +187,7 @@ OnTimer5000:
L_Return_1:
set $@FIGHT_CAVE_PLAYER_COUNT, 0;
- areatimer "029-3", 20, 20, 70, 60, 10, "Parua::OnTick";
+ areatimer 0, "029-3", 20, 20, 70, 60, 10, "Parua::OnTick";
end;
L_CaveLogic:
@@ -215,7 +215,7 @@ L_NextRound:
goto L_CleanUp;
set $@FIGHT_CAVE_POINTS, $@FIGHT_CAVE_LEVEL;
- areatimer "029-3", 20, 20, 70, 60, 10, "Parua::OnNewRound";
+ areatimer 0, "029-3", 20, 20, 70, 60, 10, "Parua::OnNewRound";
set $@candor_npctalk$, "The next round (level " + $@FIGHT_CAVE_LEVEL + ") is starting with " + $@FIGHT_CAVE_PLAYER_COUNT + " player(s) left alive.";
donpcevent "#CandorAnnouncer::OnCommandTalk";
@@ -360,7 +360,7 @@ L_CleanUp:
npctalk strnpcinfo(0), "Game Over";
set $@candor_npctalk$, "The dungeon is now ready for its next victims.";
donpcevent "#CandorAnnouncer::OnCommandTalk";
- areatimer "029-3", 20, 20, 70, 60, 10, "Parua::OnReward";
+ areatimer 0, "029-3", 20, 20, 70, 60, 10, "Parua::OnReward";
set $@FIGHT_CAVE_STATUS, 0;
set $@ANNOUNCE_TIME, 0;
set $@FIGHT_CAVE_PAID, 0;
diff --git a/world/map/npc/030-4/mana_battery.txt b/world/map/npc/030-4/mana_battery.txt
index aea601c5..15ff40c3 100644
--- a/world/map/npc/030-4/mana_battery.txt
+++ b/world/map/npc/030-4/mana_battery.txt
@@ -197,7 +197,7 @@ OnTimer5000:
L_Return_1:
set $@XmasBossPlayerCount, 0;
- areatimer "030-4", 0, 0, 60, 60, 10, "AniManOMat::OnTick";
+ areatimer 0, "030-4", 0, 0, 60, 60, 10, "AniManOMat::OnTick";
end;
L_CaveLogic:
@@ -294,7 +294,7 @@ L_Finished:
goto L_CleanUp;
L_CleanUp:
- areatimer "030-4", 0, 0, 50, 50, 10, "AniManOMat::OnReward";
+ areatimer 0, "030-4", 0, 0, 50, 50, 10, "AniManOMat::OnReward";
set $@XmasBossPlayerCount, 0;
set $@XmasBossRound, 0;
set $@BombTimer, 0;
@@ -338,7 +338,7 @@ L_EndNice:
end;
OnCommandChamberReset:
- areatimer "030-4", 0, 0, 50, 50, 10, "AniManOMat::OnReward";
+ areatimer 0, "030-4", 0, 0, 50, 50, 10, "AniManOMat::OnReward";
set $@XmasBattleStatus, 0;
set $@XmasBossPlayerCount, 0;
set $@XmasBossRound, 0;
diff --git a/world/map/npc/031-4/cindyCave.txt b/world/map/npc/031-4/cindyCave.txt
index 33c3a16f..c97b166d 100644
--- a/world/map/npc/031-4/cindyCave.txt
+++ b/world/map/npc/031-4/cindyCave.txt
@@ -131,7 +131,7 @@ OnTimer5000:
L_Return_1:
set $@FIGHT_YETI_PLAYER_COUNT, 0;
- areatimer "031-4", 0, 0, 95, 91, 10, "Cindy::OnTick";
+ areatimer 0, "031-4", 0, 0, 95, 91, 10, "Cindy::OnTick";
end;
L_CaveLogic:
@@ -184,7 +184,7 @@ OnPetDeath:
end;
L_CleanUp:
- areatimer "031-4", 0, 0, 95, 91, 10, "Cindy::OnReward";
+ areatimer 0, "031-4", 0, 0, 95, 91, 10, "Cindy::OnReward";
set $@FIGHT_YETI_STATUS, 0;
set $@FIGHT_YETI_PLAYER_COUNT, 0;
set $@FIGHT_YETI_WAVE, 0;
diff --git a/world/map/npc/033-1/kimarr.txt b/world/map/npc/033-1/kimarr.txt
index 6650198f..cbe2b289 100644
--- a/world/map/npc/033-1/kimarr.txt
+++ b/world/map/npc/033-1/kimarr.txt
@@ -196,7 +196,7 @@ L_Action:
goto L_Died;
// Checking if there is more than 1 player in the fight area
if (getareausers("033-1", 79, 28, 88, 42) > 1)
- areatimer "033-1", 79, 28, 88, 42, 10, "Kimarr::OnTooMany";
+ areatimer 0, "033-1", 79, 28, 88, 42, 10, "Kimarr::OnTooMany";
if ($@Fluffy_Time == 180)
npctalk strnpcinfo(0), strcharinfo(0) + ", you have 3 minutes.";
diff --git a/world/map/npc/051-3/ambush.txt b/world/map/npc/051-3/ambush.txt
index da12b306..7d659710 100644
--- a/world/map/npc/051-3/ambush.txt
+++ b/world/map/npc/051-3/ambush.txt
@@ -72,8 +72,8 @@ OnTimer9000:
end;
OnTimer11000:
- areatimer "051-3", 22, 12, 102, 97, 500, "#BndtTl::OnOuch";
- areatimer "051-3", 22, 12, 102, 97, 3000, "#BndtTl::OnA";
+ areatimer 0, "051-3", 22, 12, 102, 97, 500, "#BndtTl::OnOuch";
+ areatimer 0, "051-3", 22, 12, 102, 97, 3000, "#BndtTl::OnA";
stopnpctimer;
setnpctimer 0;
end;
diff --git a/world/map/npc/051-3/reinforcements.txt b/world/map/npc/051-3/reinforcements.txt
index 73236dec..5870671c 100644
--- a/world/map/npc/051-3/reinforcements.txt
+++ b/world/map/npc/051-3/reinforcements.txt
@@ -49,7 +49,7 @@ OnRnfrcmts:
areamonster "051-3", 29, 25, 48, 39, "", 1065, 3, "Door::OnB";
initnpctimer;
mapannounce "051-3", "Bandit Lords : Do not let them escape!!" , 0;
- areatimer "051-3", 25, 20, 80, 85, 10, "Door::OnDRnfrcmts";
+ areatimer 0, "051-3", 25, 20, 80, 85, 10, "Door::OnDRnfrcmts";
end;
OnB:
@@ -72,7 +72,7 @@ L_OpenDoor:
set $@illia_progress, 3;
callfunc "UpdateIlliaProgress";
set $@illia_max_time, $@illia_max_time + 300;
- areatimer "051-3", 25, 20, 80, 85, 10, "Door::OnKeyFound";
+ areatimer 0, "051-3", 25, 20, 80, 85, 10, "Door::OnKeyFound";
stopnpctimer;
setnpctimer 0;
end;
diff --git a/world/map/npc/052-1/channelling.txt b/world/map/npc/052-1/channelling.txt
index 565f96fd..5eb3dfbf 100644
--- a/world/map/npc/052-1/channelling.txt
+++ b/world/map/npc/052-1/channelling.txt
@@ -141,6 +141,10 @@ L_Return:
goto L_Hint;
end;
+OnCast:
+ callfunc "StartChannelling";
+ end;
+
OnCommandSt:
initnpctimer;
end;
@@ -259,7 +263,7 @@ S_CheckChannelling:
set $@illia_channelling_status_msg$, $@illia_char_channelling$ + ": Damn! It faded a little.";
if ($@illia_channelling_status_msg$ != "")
- areatimer "052-1", 1, 1, 100, 80, 0, "#Power Circle::OnMPSC";
+ areatimer 0, "052-1", 1, 1, 100, 80, 0, "#Power Circle::OnMPSC";
return;
@@ -328,4 +332,8 @@ L_ChannellingFail:
L_ShouldNotBeHere:
heal -Hp, 0;
end;
+
+OnInit:
+ registercmd "#catalazuli", strnpcinfo(0)+"::OnCast";
+ end;
}
diff --git a/world/map/npc/052-2/lobby.txt b/world/map/npc/052-2/lobby.txt
index efc0a20a..1b36d929 100644
--- a/world/map/npc/052-2/lobby.txt
+++ b/world/map/npc/052-2/lobby.txt
@@ -337,7 +337,7 @@ L_ChaseLuvia:
set $@illia_progress, 6;
callfunc "UpdateIlliaProgress";
set $@illia_max_time, $@illia_max_time + 360;
- areatimer "052-2", 19, 18, 48, 43, 2000, "#LuviaShadow::OnNN";
+ areatimer 0, "052-2", 19, 18, 48, 43, 2000, "#LuviaShadow::OnNN";
end;
S_GetHeroRect:
diff --git a/world/map/npc/052-2/partyroom.txt b/world/map/npc/052-2/partyroom.txt
index 02d7a7ac..ec6d2a64 100644
--- a/world/map/npc/052-2/partyroom.txt
+++ b/world/map/npc/052-2/partyroom.txt
@@ -182,7 +182,7 @@ S_SpawnWitchGuard:
misceffect FX_GROUND_SPAWN;
monster "052-2", getx(), gety(), "", 1103, 1, "#LuviaDaemon::OnWGD";
detachrid;
- areatimer "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnWGS";
+ areatimer 0, "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnWGS";
return;
OnTimer30000:
@@ -198,7 +198,7 @@ OnTimer30000:
L_TriggerTrance:
set $@illia_level_7_progress, 3;
set $@illia_luvia_trance_delay, 0;
- areatimer "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnTT";
+ areatimer 0, "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnTT";
setnpctimer 0;
end;
@@ -217,9 +217,9 @@ OnDeath:
mapannounce "052-2", "Luvia : How? By mere humans! But we will see again! Enjoy your victory while it lasts, " + $@ILLIA_HERO$ + "!!", 0;
set $@illia_bp, $Illia_Luvia_Harvest * 16 / 10 + 120;
- areatimer "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnBP";
+ areatimer 0, "052-2", 73, 11, 115, 49, 0, "#LuviaDaemon::OnBP";
- areatimer "052-2", 73, 11, 115, 49, 2000, "#LuviaDaemon::OnW00t";
+ areatimer 0, "052-2", 73, 11, 115, 49, 2000, "#LuviaDaemon::OnW00t";
set $@illia_progress, 8;
callfunc "UpdateIlliaProgress";
diff --git a/world/map/npc/052-2/storage.txt b/world/map/npc/052-2/storage.txt
index 8abbb732..a8582408 100644
--- a/world/map/npc/052-2/storage.txt
+++ b/world/map/npc/052-2/storage.txt
@@ -42,7 +42,7 @@ OnCommandStart:
set $@illia_storage_max_items, 20;
set $@illia_storage_deviation, (8 + ($Illia_Luvia_Harvest*70)/100)*3;
initnpctimer;
- areatimer "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnStart";
+ areatimer 0, "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnStart";
end;
OnStart:
@@ -64,7 +64,7 @@ OnTimer1000:
OnTimer1500:
// See the note above.
enablenpc "#ItemsInvoker";
- areatimer "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnItem";
+ areatimer 0, "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnItem";
misceffect FX_GROUND_SPAWN;
end;
@@ -109,7 +109,7 @@ L_ItemSpawn:
L_MakeSpecialMonster:
monster "052-2", $@item_invoke_x, $@item_invoke_y, "", 1103, 1, "#ItemsInvoker::OnDeath";
- areatimer "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnWtf";
+ areatimer 0, "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnWtf";
set $@illia_storage_max_items, $@illia_storage_max_items - 1;
end;
@@ -121,7 +121,7 @@ L_MakeMonster:
L_MakeSpecialItem:
makeitem $@illia_storage_special_items[rand(getarraysize($@illia_storage_special_items))], rand(2, 4), "052-2", $@item_invoke_x, $@item_invoke_y;
- areatimer "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnWow";
+ areatimer 0, "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnWow";
set $@illia_storage_max_items, $@illia_storage_max_items - 1;
set @r, 0;
end;
@@ -152,7 +152,7 @@ L_Stop:
set $@illia_progress, 7;
callfunc "UpdateIlliaProgress";
set $@illia_max_time, $@illia_max_time + 900;
- areatimer "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnStop";
+ areatimer 0, "052-2", 19, 60, 35, 78, 10, "#ItemsInvoker::OnStop";
end;
OnDeath:
diff --git a/world/map/npc/commands/_atcommand_local.txt.example b/world/map/npc/commands/_atcommand_local.txt.example
new file mode 100644
index 00000000..a195d580
--- /dev/null
+++ b/world/map/npc/commands/_atcommand_local.txt.example
@@ -0,0 +1,12 @@
+-|script|GM|32767
+{
+ end;
+
+OnInit:
+ // define permissions here
+ set .zeny, G_ADMIN;
+
+ // permissions for events
+ set .killthegm, G_EVENT;
+ end;
+}
diff --git a/world/map/npc/commands/_import.txt b/world/map/npc/commands/_import.txt
new file mode 100644
index 00000000..7efe4111
--- /dev/null
+++ b/world/map/npc/commands/_import.txt
@@ -0,0 +1,4 @@
+npc: npc/commands/_procedures.txt
+npc: npc/commands/_atcommand_local.txt
+npc: npc/commands/zeny.txt
+npc: npc/commands/marry.txt
diff --git a/world/map/npc/commands/_procedures.txt b/world/map/npc/commands/_procedures.txt
new file mode 100644
index 00000000..77c1c7e9
--- /dev/null
+++ b/world/map/npc/commands/_procedures.txt
@@ -0,0 +1,53 @@
+// ARGV Splitter
+// takes @args$ and splits it properly so that '@cmd "foo bar" baz' is ['foo bar','baz'] instead of ['foo','bar','baz']
+// input: @args$ (string)
+// output: @argv$ (array) and @argv (array)
+function|script|argv_splitter
+{
+ explode .@fragments$, @args$, " ";
+ set .@e, 0;
+ set .@total, getarraysize(.@fragments$);
+ set .@NULL$, chr(3); // HACK: we use .@NULL$ as a workaround because we can't do "\0"
+ goto L_Check;
+
+L_Check:
+ setarray .@check$[0], "", .@NULL$, .@NULL$;
+ explode .@check$, .@fragments$[.@e], "\""; // check if the fragment contains a quote
+ if (.@check$[0] == "" && .@check$[1] != .@NULL$ && .@check$[1] != "" && .@check$[2] == .@NULL$)
+ set .@string$, .@check$[1]; // begin substring
+ elif (.@check$[0] != "" && .@check$[1] == "" && .@check$[2] == .@NULL$)
+ goto L_EndSubString; // end substring
+ elif (.@string$ != "" && .@check$[0] != "" && .@check$[1] == .@NULL$ && .@check$[2] == .@NULL$)
+ set .@string$, .@string$ +" "+ .@check$[0]; // part of the substring
+ elif (.@check$[2] != .@NULL$) goto L_Set2; // the the argument is quoted but there is no space
+ else goto L_Set;
+ goto L_CheckAfter;
+
+L_Set:
+ setarray @argv$[.@t], .@check$[0]; // not in a substring so push right away
+ setarray @argv[.@t], .@check$[0]; // not in a substring so push right away
+ set .@t, .@t + 1;
+ goto L_CheckAfter;
+
+L_Set2:
+ setarray @argv$[.@t], .@check$[1]; // not in a substring so push right away
+ setarray @argv[.@t], .@check$[1]; // not in a substring so push right away
+ set .@t, .@t + 1;
+ goto L_CheckAfter;
+
+L_EndSubString:
+ set .@string$, .@string$ + " " + .@check$[0];
+ setarray @argv$[.@t], .@string$; // push in the array
+ setarray @argv[.@t], .@string$; // push in the array
+ set .@t, .@t + 1;
+ set .@string$, ""; // clean
+ goto L_CheckAfter;
+
+L_CheckAfter:
+ set .@e, .@e + 1;
+ if (.@e > .@total) goto L_Done; // the @argv$ array is built
+ goto L_Check; // not done yet
+
+L_Done:
+ return;
+}
diff --git a/world/map/npc/commands/marry.txt b/world/map/npc/commands/marry.txt
new file mode 100644
index 00000000..39efe6b8
--- /dev/null
+++ b/world/map/npc/commands/marry.txt
@@ -0,0 +1,69 @@
+-|script|special-marry|32767
+{
+ set .@target_id, getcharid(3, @args$);
+ if (.@target_id < 1 || !(isloggedin(.@target_id)) || .@target_id == BL_ID) goto L_NotFound;
+ if (PARTNER || get(PARTNER, .@target_id)) goto L_AlreadyMarried;
+ if (isin("014-1",29,36,34,39) == 0 && isin("001-1",20,27,22,27) == 0) goto L_NotInArea;
+ if (distance(BL_ID, .@target_id) != 1) goto L_AwayFromPartner;
+ if (BaseLevel < WEDDING_MIN_LEVEL || get(BaseLevel, .@target_id) < WEDDING_MIN_LEVEL) goto L_TooYoung;
+ if (getequipid(equip_shield) != 702 || getequipid(equip_shield, @args$) != 702) goto L_NoRing;
+
+ if (get(@marriage[0], .@target_id) == BL_ID) goto L_Proceed;
+
+ setarray @marriage[0], .@target_id, gettimetick(2);
+ addtimer (.timeout * 1000), strnpcinfo(0) + "::OnTimeout";
+ announce strcharinfo(0) + " is asking " + strcharinfo(0, .@target_id) + " for marriage.", 2;
+ message strcharinfo(0, .@target_id), "Marriage : ##3##B" + strcharinfo(0) + " wishes to marry you. To accept, write `##1#marry "+strcharinfo(0)+"##3` within the next "+.timeout+" seconds.";
+ end;
+
+L_NotFound:
+ message strcharinfo(0), "Marriage : ##3##BThe target player is either not found or yourself.";
+ end;
+
+L_TooYoung:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to be at least level "+ WEDDING_MIN_LEVEL +".";
+ end;
+
+L_NoRing:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to have ["+ getitemlink("WeddingRing") +"] equipped.";
+ end;
+
+L_AwayFromPartner:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to be standing next to each other.";
+ end;
+
+L_NotInArea:
+ message strcharinfo(0), "Marriage : ##3##BYou are not standing in a designated marriage area.";
+ end;
+
+L_Proceed:
+ if ((gettimetick(2) - .timeout) > get(@marriage[1], .@target_id)) goto L_TooLate;
+ set PARTNER, CHAR_ID, .@target_id;
+ if (PARTNER == get(CHAR_ID, .@target_id)) goto L_Success;
+ set PARTNER, 0, .@target_id;
+ set PARTNER, 0;
+ end;
+
+L_Success:
+ announce strcharinfo(0) + " and " + strcharinfo(0, .@target_id) + " are now married.", 2;
+ end;
+
+OnTimeout:
+ goto L_TooLate;
+
+L_TooLate:
+ message strcharinfo(0), "Marriage : ##3##BThe proposal expired. Please try again.";
+ message strcharinfo(0, @marriage[0]), "Marriage : ##3##BThe proposal expired. Please try again.";
+ set @marriage[0], 0, @marriage[0];
+ set @marriage[0], 0;
+ end;
+
+L_AlreadyMarried:
+ message strcharinfo(0), "Marriage : ##3##BYou"+ if_then_else(PARTNER, " are", "r partner is") +" already married.";
+ end;
+
+OnInit:
+ set .timeout, 30; // timeout for proposal
+ registercmd "#marry", strnpcinfo(0); // we NEED to use a # before `marry` because otherwise manaplus does not strip colors
+ end;
+}
diff --git a/world/map/npc/commands/zeny.txt b/world/map/npc/commands/zeny.txt
new file mode 100644
index 00000000..9215637a
--- /dev/null
+++ b/world/map/npc/commands/zeny.txt
@@ -0,0 +1,77 @@
+-|script|@zeny|32767
+{
+ if (GM < get(.zeny, "GM") && GM < G_SYSOP) goto L_GM;
+ callfunc "argv_splitter";
+ set .@target_id, BL_ID;
+ if (@argv$[1] != "") set .@target_id, getcharid(3, @argv$[1]);
+ if (@argv$[1] != "" && !(isloggedin(.@target_id))) goto L_Failed; // do NOT fallback to self
+ if (@argv$[0] == "--") goto L_Remove;
+ if (@argv$[0] == "---") goto L_RemoveAll;
+ if (@argv$[0] == "++") goto L_Max;
+ if (@argv$[0] == "+++") goto L_MaxAll;
+ set .@delta, @argv[0]; // ± zeny
+ set .@zeny, get(Zeny, .@target_id); // get the number of zeny in char
+ set .@bank, get(#BankAccount, .@target_id); // get number of zeny in (world) account
+ set .@new_zeny, .@zeny + .@delta; // new balance in char
+ if (.@new_zeny < 0) goto L_MaybeRemoveBank; // zeny would be below 0 so check if we can take from bank
+ if (.@new_zeny > .max_zeny) goto L_MaybeAddBank; // zeny would be over the limit so check if we can store in bank
+ set Zeny, (.@zeny + .@delta), .@target_id;
+ goto L_Success;
+
+L_Remove:
+ set Zeny, 0, .@target_id;
+ goto L_Success;
+
+L_RemoveAll:
+ set Zeny, 0, .@target_id;
+ set #BankAccount, 0, .@target_id;
+ goto L_Success;
+
+L_Max:
+ set Zeny, .max_zeny, .@target_id;
+ goto L_Success;
+
+L_MaxAll:
+ set Zeny, .max_zeny, .@target_id;
+ set #BankAccount, .max_int, .@target_id;
+ goto L_Success;
+
+L_MaybeAddBank:
+ set .@new_bank, (.@bank + (.@new_zeny - .max_zeny));
+ if (.@new_bank > .max_int || .@new_bank < 0) goto L_OutOfBounds;
+ set Zeny, .max_zeny, .@target_id;
+ set #BankAccount, .@new_bank, .@target_id;
+ goto L_Success;
+
+L_MaybeRemoveBank:
+ if ((.@bank + .@new_zeny) < 0) goto L_OutOfBounds;
+ set Zeny, 0, .@target_id;
+ set #BankAccount, (.@bank + .@new_zeny), .@target_id;
+ goto L_Success;
+
+L_OutOfBounds:
+ // XXX: maybe we could also take from other chars from the same accout?
+ message strcharinfo(0), "zeny : Impossible to proceed! This would cause the player to have less than 0 zeny or more than " + .max_int + ".";
+ end;
+
+L_Failed:
+ // XXX: should we allow GMs to change zeny of users that are not logged in?
+ message strcharinfo(0), "zeny : Impossible to attach to the target player.";
+ end;
+
+L_Success:
+ gmlog "@zeny " + @args$;
+ message strcharinfo(0), "zeny : The operation succeeded.";
+ end;
+
+L_GM:
+ message strcharinfo(0), "zeny : GM command is level "+ get(.zeny, "GM") +", but you are level " + GM;
+ end;
+
+OnInit:
+ set .max_zeny, 1000000000; // hardcoded in tmwa
+ set .max_int, 2147483647; // max int32 value
+ registercmd chr(ATCMD_SYMBOL) + "zeny", strnpcinfo(0);
+ registercmd chr(ATCMD_SYMBOL) + "charzeny", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/doc/magic b/world/map/npc/doc/magic
deleted file mode 100644
index 8a2b84e1..00000000
--- a/world/map/npc/doc/magic
+++ /dev/null
@@ -1,23 +0,0 @@
-Nibble use:
----------------
-== QUEST_MAGIC
- N0, N1: Auldsbel
- N2: druid tree quest, mouboo quest (shared)
- N3: Sagatha unhappiness counter
- N4, N5: Sagatha
- N6, N7: Swords
-== QUEST_MAGIC2
- N0: Evil Earth Spirit
- N1: Elanore
- N2: Wyara
- N3: Elanore subquests (Cure Kadiya)
- N4-N7: may be messy at this point
-
-The various magic scripts pack their status into these variables.
-Locally, they use `@Q_status' to maintain the state, and use a function
-`S_update_var' to update it. This is all re-using the same code, setting
-the `@Q_MASK' and `@Q_SHIFT' variables appropriately.
-
- There are a few exceptions (such as the Kadiya quest) wherein
-a separate helper function sets a dedicated local variable, or some hackery
-in Auldsbel wherein we read stati directly, merely to enable certain options.
diff --git a/world/map/npc/functions/debug.txt b/world/map/npc/functions/debug.txt
index 44af4d40..556e501b 100755
--- a/world/map/npc/functions/debug.txt
+++ b/world/map/npc/functions/debug.txt
@@ -5,7 +5,7 @@ function|script|Debug
if(!@debug_npc) goto L_Begin;
mes "The debug NPCs have been deprecated. Please use this magic spell instead:";
mes "";
- mes "%%E ##a"+ getspellinvocation("debug0") +"##0";
+ mes "%%E ##a#debug##0";
set @debug_npc, 0;
goto L_Close;
@@ -831,13 +831,13 @@ S_Update_Mask:
return;
L_GetAllMagic:
- setskill SKILL_MAGIC, 2;
- setskill SKILL_MAGIC_LIFE, 2;
- setskill SKILL_MAGIC_WAR, 2;
- setskill SKILL_MAGIC_TRANSMUTE, 2;
- setskill SKILL_MAGIC_NATURE, 2;
- setskill SKILL_MAGIC_ASTRAL, 2;
- setskill SKILL_MAGIC_DARK, 2;
+ setskill SKILL_MAGIC, 5;
+ setskill SKILL_MAGIC_LIFE, 5;
+ setskill SKILL_MAGIC_WAR, 5;
+ setskill SKILL_MAGIC_TRANSMUTE, 5;
+ setskill SKILL_MAGIC_NATURE, 5;
+ setskill SKILL_MAGIC_ASTRAL, 5;
+ setskill SKILL_MAGIC_DARK, 5;
set @mexp, 8000;
callsub S_Update_Mask;
mes "Magic skills added.";
@@ -869,13 +869,13 @@ L_AddAll:
setskill SKILL_RESIST_POISON, 9;
setskill SKILL_ASTRAL_SOUL, 9;
setskill SKILL_RAGING, 9;
- setskill SKILL_MAGIC, 2;
- setskill SKILL_MAGIC_LIFE, 2;
- setskill SKILL_MAGIC_WAR, 2;
- setskill SKILL_MAGIC_TRANSMUTE, 2;
- setskill SKILL_MAGIC_NATURE, 2;
- setskill SKILL_MAGIC_ASTRAL, 2;
- setskill SKILL_MAGIC_DARK, 2;
+ setskill SKILL_MAGIC, 5;
+ setskill SKILL_MAGIC_LIFE, 5;
+ setskill SKILL_MAGIC_WAR, 5;
+ setskill SKILL_MAGIC_TRANSMUTE, 5;
+ setskill SKILL_MAGIC_NATURE, 5;
+ setskill SKILL_MAGIC_ASTRAL, 5;
+ setskill SKILL_MAGIC_DARK, 5;
set @mexp, 8000;
resetstatus;
set BaseLevel, 99;
@@ -922,6 +922,16 @@ L_Close:
}
+-|script|Debug Spell|32767
+{
+ if(!debug && getgmlevel() < 99) end;
+ callfunc "Debug";
+ end;
+OnInit:
+ registercmd "@debug", "Debug Spell";
+ end;
+}
+
029-2,30,26,0|script|Debug#0|154
{
set @debug_npc, 1;
diff --git a/world/map/npc/functions/global_event_handler.txt b/world/map/npc/functions/global_event_handler.txt
index d5c20b06..e4247d18 100644
--- a/world/map/npc/functions/global_event_handler.txt
+++ b/world/map/npc/functions/global_event_handler.txt
@@ -28,6 +28,7 @@ OnPCKilledEvent:
OnPCDieEvent:
callfunc "fightclub_GoBack"; // this used by the battle master
callfunc "fightclub_event_die"; // this is used by the 1v1 arena
+ set @necromancer, 0;
end;
OnInit:
diff --git a/world/map/npc/functions/hug.txt b/world/map/npc/functions/hug.txt
new file mode 100644
index 00000000..a663ea1d
--- /dev/null
+++ b/world/map/npc/functions/hug.txt
@@ -0,0 +1,24 @@
+-|script|nonmagic-hug|32767
+{
+ explode .@name$[0], @args$, "*"; // strip the trailing *
+ set @target_id, if_then_else(.@name$[0], getcharid(3, .@name$[0]), BL_ID);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (.@name$[0] == "Tree" || .@name$[0] == "tree") set @target_id, .tree_id;
+ set .@range, 3;
+ if (distance(BL_ID, @target_id) >= .@range) end;
+ misceffect FX_HUG, strcharinfo(0);
+ if (@target_id != BL_ID) misceffect FX_HUG, @target_id;
+ if (@target_id != .tree_id) end;
+ callfunc "QuestTreeTouch";
+ close;
+
+OnInit:
+ set .tree_id, getnpcid("#DruidTree0#_M");
+ registercmd "hug", strnpcinfo(0);
+ registercmd "*hug", strnpcinfo(0);
+ registercmd "*hug*", strnpcinfo(0);
+ registercmd "hugs", strnpcinfo(0);
+ registercmd "*hugs", strnpcinfo(0);
+ registercmd "*hugs*", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/functions/strangerquiz.txt b/world/map/npc/functions/strangerquiz.txt
index 8da3f65a..3427a0ee 100644
--- a/world/map/npc/functions/strangerquiz.txt
+++ b/world/map/npc/functions/strangerquiz.txt
@@ -3,6 +3,6 @@ function|script|StrangerQuiz
{
// param @quizparam$$
// return in @quizanswer$
- set @quizanswer$, getspellinvocation(@quizparam$);
+ set @quizanswer$, (@quizparam$);
return;
}
diff --git a/world/map/npc/functions/superdebug.txt b/world/map/npc/functions/superdebug.txt
index 5654dd4c..140e703a 100644
--- a/world/map/npc/functions/superdebug.txt
+++ b/world/map/npc/functions/superdebug.txt
@@ -34,32 +34,36 @@ L_Holiday:
L_XmasDebug:
gmlog strcharinfo(0) + " accessed the Xmas debug.";
callfunc "XmasDebug";
- end;
+ goto L_Close;
L_HalloweenDebug:
gmlog strcharinfo(0) + " accessed the Halloween debug.";
callfunc "HalloweenDebug";
- end;
+ goto L_Close;
L_Event:
if(getgmlevel() < 60) goto L_GM;
gmlog strcharinfo(0) + " accessed the GM event debug.";
callfunc "GmDebug";
- close;
+ goto L_Close;
L_StoneBoard:
if (getgmlevel() < 30) goto L_GM;
callfunc "SBConfig";
- close;
+ goto L_Close;
L_MOTD:
if (getgmlevel() < 40) goto L_GM;
callfunc "MOTDConfig";
- close;
+ goto L_Close;
L_GM:
mes "[Numa]";
mes "I'm awfully sorry.";
mes "You do not have the required GM level to perform this action.";
- close;
+ goto L_Close;
+
+L_Close:
+ close2; // FIXME: replace with npc action 5
+ return;
}
diff --git a/world/map/npc/items/check_wand.txt b/world/map/npc/items/check_wand.txt
index 5a339049..93993c53 100644
--- a/world/map/npc/items/check_wand.txt
+++ b/world/map/npc/items/check_wand.txt
@@ -1,67 +1,2 @@
// Wands
// Author: Wushin
-function|script|WandMana
-{
- if(isin("009-7", $@fightclub_x1, $@fightclub_y1, $@fightclub_x2, $@fightclub_y2) && ((@Duel_Fighter != 1) || ($@Duel_NoMagic == 1)))
- goto L_Return;
- callfunc "CheckWand";
- set @WandCost, (@Wand * (BaseLevel / 15) + 2);
- set @WandAttack, 0;
- if (!(@Wand))
- goto L_NoWand;
- if (Sp >= @WandCost)
- goto L_Attack;
- goto L_LowSp;
-
-L_Attack:
- set Sp, (Sp - @WandCost);
- set @WandAttack, 1;
- goto L_Return;
-
-L_NoWand:
- message strcharinfo(0), "You need a wand Equipped!";
- set @WandAttack, 0;
- goto L_Return;
-
-L_LowSp:
- message strcharinfo(0), "Out of Mana";
- set @WandAttack, 0;
- goto L_Return;
-
-L_Return:
- return;
-}
-function|script|CheckWand
-{
- setarray $@Wands, 758, 1171;
- setarray $@WandsPwr, 2, 1;
- setarray $@WandsAnim, 35, 33;
- set @Wand, 0;
- set @wand_loop, 0;
- goto L_Loop;
-
-L_Loop:
- if ((getequipid(equip_hand1) == $@Wands[@wand_loop]) || (getequipid(equip_hand2) == $@Wands[@wand_loop]))
- goto L_SetWand;
- goto L_LoopAgain;
-
-L_SetWand:
- set @Wand, $@WandsPwr[@wand_loop];
- set @WandID, $@WandsAnim[@wand_loop];
- if (QL_MORGAN == 2)
- goto L_SetCastOnce;
- goto L_Return;
-
-L_LoopAgain:
- set @wand_loop, (@wand_loop + 1);
- if (@wand_loop >= getarraysize($@Wands))
- goto L_Return;
- goto L_Loop;
-
-L_SetCastOnce:
- set QL_MORGAN, 3;
- goto L_Return;
-
-L_Return:
- return;
-}
diff --git a/world/map/npc/items/magic_gm_top_hat.txt b/world/map/npc/items/magic_gm_top_hat.txt
index 129aa5c0..dfd114d2 100644
--- a/world/map/npc/items/magic_gm_top_hat.txt
+++ b/world/map/npc/items/magic_gm_top_hat.txt
@@ -1,21 +1,25 @@
-function|script|ActivateMagicGMTophat
+-|script|ActivateMagicGMTophat|32767
{
- if (getgmlevel() < 60) goto L_Return;
+ if (GM < get(.killthegm, "GM") && GM < G_SYSOP) end;
+ if (getequipid(equip_head) != 888) end;
getinventorylist;
if ((checkweight("MurdererCrown", 1) == 0) || (@inventorylist_count == 100))
goto L_Inventory;
// Get the current reward of the event. This may be changed later
getitem "MurdererCrown", 1;
+ // Set HP and SP to max
+ heal MaxHp, MaxSp;
// Display an effect
misceffect FX_CHANNELLING_CAST, strcharinfo(0);
// Log the usage of this spell
gmlog strcharinfo(0)+" used the Magic GM Top Hat.";
- return;
+ end;
L_Inventory:
message strcharinfo(0), "You cannot create this item. You're too heavy or you don't have a free slot.";
- return;
+ end;
-L_Return:
- return;
+OnInit:
+ registercmd "#pullrabbit", strnpcinfo(0);
+ end;
}
diff --git a/world/map/npc/magic/README.md b/world/map/npc/magic/README.md
new file mode 100644
index 00000000..a9dedb6e
--- /dev/null
+++ b/world/map/npc/magic/README.md
@@ -0,0 +1,63 @@
+# To-do
+- [ ] finish the missing spells and push them so they can be tested
+
+---
+---
+to see other things that needs to be done do a grep for `TODO`, `FIXME` in this folder.
+To see a list of things that needs further thoughts do a grep for `XXX`.
+
+---
+---
+
+- [ ] check the new builtins and make sure they work as intended
+ - [ ] `puppet`
+ - [ ] check what happens when making a puppet whose name already exist (maybe it replaces?)
+ - [ ] `destroy`
+ - [ ] `registercmd`
+ - [ ] check what happens when registering a command that was already registered
+ - [ ] `target`
+ - [ ] `get`
+ - [ ] the new `set`
+ - [ ] `min`
+ - [ ] `max`
+ - [ ] `pow`
+ - [ ] `sqrt`
+ - [ ] `cbrt`
+ - [ ] `elttype`
+ - [ ] `eltlvl`
+ - [ ] `injure`
+ - [ ] `elif`
+ - [ ] `else`
+ - [ ] `getnpcid`
+ - [ ] `overrideattack`
+ - [ ] `summon`
+ - [ ] `addnpctimer`
+ - [ ] `explode`
+ - [ ] `foreach`
+ - [ ] modified `areatimer`
+ - [ ] `aggravate`
+ - [ ] `getdir`
+ - [ ] `distance`
+ - [ ] `if_then_else`
+
+---
+- [ ] test the spells
+ - [ ] test with no target
+ - [ ] test with a npc target
+ - [ ] random npc not part of any quest
+ - [ ] injured mouboo
+ - [ ] also test on a **player** with the name `Mouboo` or `mouboo`
+ - [ ] druid tree
+ - [ ] test with a mob target
+ - [ ] mob with clear path (walkable)
+ - [ ] mob with no clear path (unwalkable, blocked by collision)
+ - [ ] mob out of attack range
+ - [ ] test with a player target
+ - [ ] both the caster and the target have pvp disabled
+ - [ ] both the caster and the target have pvp enabled
+ - [ ] the caster has pvp enabled and the target has pvp disabled
+ - [ ] the caster has pvp disabled and the target has pvp enabled
+ - [ ] test with the spouse as target
+
+---
+- [ ] Once everything is done, remove this file
diff --git a/world/map/npc/magic/_import.txt b/world/map/npc/magic/_import.txt
new file mode 100644
index 00000000..4118170e
--- /dev/null
+++ b/world/map/npc/magic/_import.txt
@@ -0,0 +1,38 @@
+npc: npc/magic/_procedures.txt
+npc: npc/magic/level0-wand.txt
+npc: npc/magic/level1-aggravate.txt
+npc: npc/magic/level1-experience.txt
+npc: npc/magic/level1-lesser-heal.txt
+npc: npc/magic/level1-transmute-wood.txt
+npc: npc/magic/level1-make-sulphur.txt
+npc: npc/magic/level1-flare-dart.txt
+npc: npc/magic/level1-magic-blade.txt
+npc: npc/magic/level1-grow-mauve.txt
+npc: npc/magic/level1-grow-alizarin.txt
+npc: npc/magic/level1-grow-gamboge.txt
+npc: npc/magic/level1-grow-cobalt.txt
+npc: npc/magic/level1-summon-maggots.txt
+npc: npc/magic/level1-detect-magic.txt
+npc: npc/magic/level2-arrow-hail.txt
+npc: npc/magic/level2-make-arrows.txt
+npc: npc/magic/level2-make-iron-powder.txt
+npc: npc/magic/level2-magic-knuckles.txt
+npc: npc/magic/level2-summon-snakes.txt
+npc: npc/magic/level2-summon-wickedmushroom.txt
+npc: npc/magic/level2-summon-spiky-mushroom.txt
+npc: npc/magic/level2-summon-fluffies.txt
+npc: npc/magic/level2-summon-mouboo.txt
+npc: npc/magic/level2-summon-pinkie.txt
+npc: npc/magic/level2-toxic-dart.txt
+npc: npc/magic/level2-enchant-lifestone.txt
+npc: npc/magic/level2-flying-backpack.txt
+npc: npc/magic/level2-protect.txt
+npc: npc/magic/level2-barrier.txt
+npc: npc/magic/level2-hide.txt
+npc: npc/magic/level2-happy-curse.txt
+npc: npc/magic/level2-detect-players.txt
+npc: npc/magic/level2-shear.txt
+npc: npc/magic/level2-lightning-strike.txt
+npc: npc/magic/level2-rain.txt
+npc: npc/magic/level2-lay-on-hands.txt
+npc: npc/magic/level3-necromancy.txt
diff --git a/world/map/npc/magic/_procedures.txt b/world/map/npc/magic/_procedures.txt
new file mode 100644
index 00000000..71d12605
--- /dev/null
+++ b/world/map/npc/magic/_procedures.txt
@@ -0,0 +1,135 @@
+function|script|magic_register
+{
+ debugmes ">> Register " + .invocation$ + " @ " + strnpcinfo(0);
+ registercmd .invocation$, strnpcinfo(0); // register the spell
+ set .index, $@magic_index;
+ set $@magic_index, $@magic_index + 1;
+ return;
+}
+
+function|script|magic_register2
+{
+ debugmes ">> Register " + .invocation$ + " @ " + strnpcinfo(0);
+ registercmd .invocation$, strnpcinfo(0) + "::OnCast"; // register the spell <= this spell has a puppet
+ set .index, $@magic_index;
+ set $@magic_index, $@magic_index + 1;
+ return;
+}
+
+function|script|magic_checks
+{
+ set @failed, 0;
+ if(getpvpflag(1)) set @failed, 1; // can not cast with @hide enabled
+ if((gettimetick(2) - MAGIC_CAST_TICK) < 0) set @failed, 1; // check if last debuff ended
+ if(isdead()) set @failed, 1; // can not cast when dead
+ return;
+}
+
+function|script|elt_damage
+{
+ // @edmg is damage, dmgplus(mutation), bonus_elt, malus_elt, effect
+ set @edmg[5], @edmg[0] + rand(@edmg[1]);
+ if(elttype(@target_id) == @edmg[3]) // malus
+ set @edmg[5], @edmg[5] / 3;
+ if(elttype(@target_id) == @edmg[2]) // bonus
+ set @edmg[5], ((eltlvl(@target_id) + 4) * @edmg[5]) / 4;
+ set .@source, .caster;
+ if (!.@source) set .@source, getcharid(3);
+
+ injure .@source, @target_id, @edmg[5];
+ misceffect @edmg[4], @target_id;
+ cleararray @edmg, 0, getarraysize(@edmg);
+ return;
+}
+
+function|script|melee_damage
+{
+ if ((@spellpower - rand(100)) < (get(BaseLevel, @target_id) + get(MDEF1, @target_id)))
+ injure BL_ID, @target_id, 0;
+ else injure BL_ID, @target_id, @melee_dmg[0] + rand(@melee_dmg[1]);
+ return;
+}
+
+function|script|magic_create_item
+{
+ set .@exp, (MAGIC_EXPERIENCE & (BYTE_0_MASK | BYTE_1_MASK)) >> BYTE_0_SHIFT;
+ set .@score, (.@exp + rand(min(@spellpower, ((.@exp / 3) + 1))));
+ set @create_params[2], 1; // success flag
+ if (.@score >= @create_params[1]) goto L_Perfect;
+ set @create_params[2], 0; // success flag
+ set .@score, .@score + rand(Luk) + rand(Luk);
+ if (.@score < (@create_params[1] / 3)) goto L_Backfire;
+ if (.@score < ((@create_params[1] * 2) / 3)) goto L_Iten;
+ message strcharinfo(0), "Magic : ##3##BYour spell takes on a mind of its own!";
+ if (rand(3) == 1) getitem @create_items$[1], 1; // bad item
+ return;
+
+L_Iten:
+ if (rand(5) != 2) goto L_Escape;
+ message strcharinfo(0), "Magic : ##3##BYour spell solidifies into the shape of a mysterious object!";
+ getitem "Iten", 1;
+ return;
+
+L_Escape:
+ message strcharinfo(0), "Magic : ##3##BYour spell escapes!";
+ return;
+
+L_Backfire:
+ message strcharinfo(0), "Magic : ##3##BYour spell backfires!";
+ if (rand(110) < Luk) heal 0 - ((BaseLevel+1)*(BaseLevel+2)*(rand(28)+3)), 0;
+ else heal 0 - (BaseLevel + 1), 0;
+ return;
+
+L_Perfect:
+ getitem @create_items$[0], @create_params[0]; // good item
+ return;
+}
+
+function|script|magic_exp
+{
+ set @last_index, (MAGIC_EXPERIENCE & BYTE_2_MASK) >> BYTE_2_SHIFT;
+ set @last_exp, (MAGIC_EXPERIENCE & (BYTE_0_MASK | BYTE_1_MASK)) >> BYTE_0_SHIFT;
+
+ debugmes "old spell index: " + @last_index;
+ debugmes "new spell index: " + .index;
+
+ if(getskilllv(SKILL_MAGIC) < (.level + 3) && .index != @last_index)
+ goto L_Gain;
+ debugmes "same as last spell => don't proceed";
+ goto L_Return;
+
+L_Gain:
+ if(.exp_gain < 1) goto L_Return; // only the spells that have exp register here. If you
+ // remove this line then players can cast a spell with
+ // no cost, then a spell with a reagents, then another
+ // spell with no costs and still get the exp
+ set @new_exp, @last_exp + .exp_gain;
+ if(@new_exp > (BYTE_0_MASK | BYTE_1_MASK)) set @new_exp, (BYTE_0_MASK | BYTE_1_MASK);
+ debugmes "old magic exp: "+ @last_exp;
+ debugmes "new magic exp: "+ @new_exp;
+ set MAGIC_EXPERIENCE, (MAGIC_EXPERIENCE &~ (BYTE_0_MASK | BYTE_1_MASK)) | (@new_exp << BYTE_0_SHIFT);
+ set MAGIC_EXPERIENCE, (MAGIC_EXPERIENCE &~ BYTE_2_MASK) | (.index << BYTE_2_SHIFT);
+ goto L_Return;
+
+L_Return:
+ return;
+}
+
+function|script|adjust_spellpower
+{
+ set @spellpower, MATK1 + getskilllv(SKILL_MAGIC) + getskilllv(.school) + 10;
+ if((.school != SKILL_MAGIC_NATURE) && (.school != SKILL_MAGIC_LIFE)) goto L_Return;
+ if(@args$ == "" || !@args$ || getpartnerid2() == 0) goto L_Return;
+ if(getcharid(3, @args$) < 1 || getpartnerid2() != getcharid(3, @args$) || !(isloggedin(getcharid(3, @args$))))
+ goto L_Return;
+ debugmes "You targeted your spouse!";
+ // XXX: I need a builtin to check if the target is in range of the caster
+ // XXX: the spell power increases when the target is the spouse so one could
+ // just do #modrilax (spouse) right?
+ //
+ // ... let's just forget about spouse for now
+ goto L_Return;
+
+L_Return:
+ return;
+}
diff --git a/world/map/npc/magic/level0-wand.txt b/world/map/npc/magic/level0-wand.txt
new file mode 100644
index 00000000..e38a26c7
--- /dev/null
+++ b/world/map/npc/magic/level0-wand.txt
@@ -0,0 +1,74 @@
+-|script|spell-wand|32767
+{
+ callfunc "magic_checks"; if(@failed) goto L_Failed; // << I wish we had functions that could return >>
+ callsub S_CheckWand;
+ if(@WandAttack != 1) goto L_Failed;
+
+ // here we install
+ set MAGIC_CAST_TICK, gettimetick(2) + 5; // set the new debuff
+ callfunc "adjust_spellpower";
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ overrideattack (@Wand + (@spellpower / 10)), 1200, 3, ATTACK_ICON_GENERIC, @WandID, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ end;
+
+OnAttack:
+ callsub S_CheckWand;
+ if(@WandAttack != 1) goto L_Failed;
+ if(target(BL_ID, @target_id, 22) != 22) goto L_Failed; // 0x02 | 0x04 | 0x10
+ set Sp, (Sp - @WandCost);
+ set @damage, (@Wand * (@spellpower / 3));
+ setarray @edmg,@damage,@damage,ELT_NEUTRAL,ELT_NEUTRAL,FX_MAGIC_RED; callfunc "elt_damage";
+ end;
+
+S_CheckWand:
+ set @Wand, 0;
+ set @wand_loop, 0;
+ goto S_Loop;
+
+S_Loop:
+ if ((getequipid(equip_hand1) == .Wands[@wand_loop]) || (getequipid(equip_hand2) == .Wands[@wand_loop]))
+ goto S_SetWand;
+ set @wand_loop, (@wand_loop + 1);
+ if (@wand_loop >= getarraysize(.Wands))
+ goto S_NoWand;
+ goto S_Loop;
+
+S_SetWand:
+ set @Wand, .WandsPwr[@wand_loop];
+ set @WandID, .WandsAnim[@wand_loop];
+ if (QL_MORGAN == 2)
+ set QL_MORGAN, 3;
+ set @WandCost, (@Wand * (BaseLevel / 15) + 2);
+ set @WandAttack, 0;
+ if (Sp < @WandCost)
+ goto S_LowSp;
+ set @WandAttack, 1; // everything is fine
+ return;
+
+S_NoWand:
+ message strcharinfo(0), "Wand : ##3##BYou need a wand Equipped!";
+ set @WandAttack, 0;
+ return;
+
+S_LowSp:
+ message strcharinfo(0), "Wand : ##3##BOut of Mana";
+ set @WandAttack, 0;
+ return;
+
+L_Failed:
+ //misceffect FX_ELECTRICITY_RED, strcharinfo(0); // XXX: do we show an effect on fail?
+ debugmes "cast or attack failed";
+ end;
+
+OnInit:
+ setarray .Wands[0], 758, 1171;
+ setarray .WandsPwr[0], 2, 1;
+ setarray .WandsAnim[0], 35, 33;
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "confringo"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 0;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-aggravate.txt b/world/map/npc/magic/level1-aggravate.txt
new file mode 100644
index 00000000..74316b89
--- /dev/null
+++ b/world/map/npc/magic/level1-aggravate.txt
@@ -0,0 +1,22 @@
+-|script|spell-aggravate|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 3) end;
+ if (getskilllv(.school) < .level) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ set @args$, ""; callfunc "adjust_spellpower"; // we reset @args$ because this spell should not have a target
+ set @distance, (2 + (@spellpower / 50));
+ set Sp, Sp - 3;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+ aggravate getmap(), (POS_X - @distance), (POS_Y - @distance), (POS_X + @distance), (POS_Y + @distance), SFX_DEFAULT;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "itenplz"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/level1-detect-magic.txt b/world/map/npc/magic/level1-detect-magic.txt
new file mode 100644
index 00000000..c5dff558
--- /dev/null
+++ b/world/map/npc/magic/level1-detect-magic.txt
@@ -0,0 +1,29 @@
+-|script|detect-magic|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 3) end;
+ if (getskilllv(.school) < .level) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 6; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 3;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ set .@range, (@spellpower/50)+1;
+ foreach 1, getmap(), POS_X - .@range, POS_Y - .@range, POS_X + .@range, POS_Y + .@range,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ callfunc "magic_exp";
+ end;
+
+OnNearbyNpc:
+ set .@e$, strnpcinfo(2,@target_id);
+ if(.@e$ == "#_M" || .@e$ == "#MAGIC")
+ misceffect FX_MAGIC_DEFAULT, @target_id;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "miteyo"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/level1-experience.txt b/world/map/npc/magic/level1-experience.txt
new file mode 100644
index 00000000..9492b6f2
--- /dev/null
+++ b/world/map/npc/magic/level1-experience.txt
@@ -0,0 +1,41 @@
+-|script|spell-experience|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 1) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ set @level, getskilllv(.school);
+ if (@level < .level) end;
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 1;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ callfunc "magic_exp"; // no exp for this spell
+ set @ratio, ((@last_exp*10) - rand(.MAX_MAGIC_EXP[@level]/30))/.MAX_MAGIC_EXP[@level];
+
+ set @mes$, "You feel completely overwhelmed by your magic.";
+ if(@ratio == 1) set @mes$, "You feel quite overwhelmed by your magic, but are beginning to see patterns.";
+ if(@ratio == 2) set @mes$, "You feel that you have only the bare minimum of control over your magic.";
+ if(@ratio == 3) set @mes$, "Trying to control your magic is still rather troublesome.";
+ if(@ratio == 4) set @mes$, "You feel you still have a few difficulties in controlling your magic.";
+ if(@ratio == 5) set @mes$, "You feel somewhat in control of your magic.";
+ if(@ratio == 6) set @mes$, "You feel mostly in control of your magic.";
+ if(@ratio == 7) set @mes$, "You feel quite in control of your magic.";
+ if(@ratio == 8) set @mes$, "You feel that you have very good control of your magic.";
+ if(@ratio == 9) set @mes$, "You feel in almost perfect control of your magic.";
+ if(@ratio >= 10) set @mes$, "You feel in perfect control of your magic" + if_then_else(@level >= MAX_MAGIC_LEVEL, ".", ", and seem on the verge of something more... perhaps you should see the Mana Seed to ask for more magic?");
+ if(@ratio >= 20) set @mes$, "You have perfect control of what you understand now, but there is now a distinct sensation of something more, something indescribable. If only the Mana Seed would give more magic to you...";
+ if(@ratio >= 45) set @mes$, "Magic flows naturally from you, readily and with ease. Your understanding of what you can currently control at present is flawless, far beyond your requirements to cast magic at this level.";
+ if(@ratio >= 45 && @level < MAX_MAGIC_LEVEL) set @mes$, @mes$ + " Surely the Mana Seed will more than readily offer more magic for such a proficient user.";
+ if(@level >= 5) set @mes$, "You are as proficient at magic as you can possibly be."; // this is the maximum magic level
+ message strcharinfo(0), "Magic : ##3##B"+@mes$;
+ // TODO put magic_exp somewhere
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "abizit"; // used in npcs that refer to this spell
+ set .level, 1;
+ set .exp_gain, 0;
+ callfunc "magic_register";
+ setarray .MAX_MAGIC_EXP[0], 0, 100, 1200, 8000, 40000, 65535;
+ end;
+}
diff --git a/world/map/npc/magic/level1-flare-dart.txt b/world/map/npc/magic/level1-flare-dart.txt
new file mode 100644
index 00000000..ee08e7f4
--- /dev/null
+++ b/world/map/npc/magic/level1-flare-dart.txt
@@ -0,0 +1,33 @@
+-|script|flare-dart|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 10) end;
+ set @level, getskilllv(.school);
+ if (@level < .level) end;
+ if (@level <= 2 && countitem("SulphurPowder") >= 1) delitem "SulphurPowder", 1;
+ elif (@level <= 2) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 10;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ set @damage, sqrt(@spellpower) * 5;
+ set @dmg_bonus, (BaseLevel/3) + 5;
+ overrideattack (@spellpower/50)+3, 1200, 4, ATTACK_ICON_GENERIC, 34, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ end;
+
+OnAttack:
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ if (target(BL_ID, @target_id, 50) != 50) end; // 0x20 | 0x02 | 0x10
+ setarray @edmg[0], @damage, @dmg_bonus, ELT_WATER, ELT_FIRE, FX_MAGIC_BLACK;
+ callfunc "elt_damage";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "flar"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-grow-alizarin.txt b/world/map/npc/magic/level1-grow-alizarin.txt
new file mode 100644
index 00000000..64593975
--- /dev/null
+++ b/world/map/npc/magic/level1-grow-alizarin.txt
@@ -0,0 +1,37 @@
+-|script|grow-alizarin|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 4) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("AlizarinHerb") < 1 || countitem("Root") < 1) end;
+ delitem "AlizarinHerb", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 2; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmap(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1032, 1, (@spellpower*50)+10000;
+ set @summon[0], @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modriphoo"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-grow-cobalt.txt b/world/map/npc/magic/level1-grow-cobalt.txt
new file mode 100644
index 00000000..c094fe6f
--- /dev/null
+++ b/world/map/npc/magic/level1-grow-cobalt.txt
@@ -0,0 +1,37 @@
+-|script|grow-cobalt|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 4) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("CobaltHerb") < 1 || countitem("Root") < 1) end;
+ delitem "CobaltHerb", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 2; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmap(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1030, 1, (@spellpower*50)+10000;
+ set @summon[0], @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modrisump"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-grow-gamboge.txt b/world/map/npc/magic/level1-grow-gamboge.txt
new file mode 100644
index 00000000..15bb9906
--- /dev/null
+++ b/world/map/npc/magic/level1-grow-gamboge.txt
@@ -0,0 +1,37 @@
+-|script|grow-gamboge|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 4) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("GambogeHerb") < 1 || countitem("Root") < 1) end;
+ delitem "GambogeHerb", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 2; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmap(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1031, 1, (@spellpower*50)+10000;
+ set @summon[0], @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modriyikam"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-grow-mauve.txt b/world/map/npc/magic/level1-grow-mauve.txt
new file mode 100644
index 00000000..6cc15955
--- /dev/null
+++ b/world/map/npc/magic/level1-grow-mauve.txt
@@ -0,0 +1,37 @@
+-|script|grow-mauve|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 4) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("MauveHerb") < 1 || countitem("Root") < 1) end;
+ delitem "MauveHerb", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 2; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ setarray @summon[0], 0, (getskilllv(.school)/2)+1;
+ callfunc "magic_exp";
+ addtimer 4000-(@spellpower-9), strnpcinfo(0)+"::OnSummon";
+ end;
+
+OnSummon:
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ callsub S_SummonAll;
+ end;
+
+S_SummonAll:
+ summon getmap(), rand(POS_X-2,POS_X+2), rand(POS_Y-2,POS_Y+2), BL_ID, 1029, 1, (@spellpower*50)+10000;
+ set @summon[0], @summon[0] + 1;
+ if (@summon[0] < @summon[1]) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "modrilax"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-lesser-heal.txt b/world/map/npc/magic/level1-lesser-heal.txt
new file mode 100644
index 00000000..ef087525
--- /dev/null
+++ b/world/map/npc/magic/level1-lesser-heal.txt
@@ -0,0 +1,41 @@
+-|script|lesser-heal|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 6) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ if (getskilllv(.school) < .level) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (@args$ == "Mouboo" || @args$ == "mouboo") set @target_id, getnpcid("Mouboo");
+ set .@range, (((MATK1 + getskilllv(SKILL_MAGIC) + getskilllv(.school) + 10) / 100) + 2);
+ if (distance(BL_ID, @target_id) >= .@range) end;
+ if (PVP_CHANNEL != get(PVP_CHANNEL, @target_id) && get(PVP_CHANNEL, @target_id) != 0) end;
+ if (countitem("Lifestone") < 1) end;
+ delitem "Lifestone", 1;
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 6;
+ misceffect FX_MAGIC_WHITE, strcharinfo(0);
+ if (@target_id != BL_ID) misceffect FX_MAGIC_WHITE, @target_id;
+ // TODO gain_heal_exp
+ // TODO magic_exp
+ if (@args$ == "Mouboo" || @args$ == "mouboo") goto L_Mouboo;
+
+ if (getskilllv(SKILL_MAGIC_DARK) >= 1) sc_start SC_HALT_REGENERATE, 2000, 0;
+
+ set @heal_amount, 200, @target_id;
+ if (attachrid(@target_id) != 1) end; // XXX: to avoid the ugly attachrid method we would need some kind of `run_as` builtin
+ if (!(isdead())) heal @heal_amount, 0, 1;
+ end;
+
+L_Mouboo:
+ mes "Mouboo : ##3##BYour spell seems to have no effect on the mouboo.";
+ close;
+
+OnInit:
+ set .school, SKILL_MAGIC_LIFE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "lum"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-magic-blade.txt b/world/map/npc/magic/level1-magic-blade.txt
new file mode 100644
index 00000000..7c286678
--- /dev/null
+++ b/world/map/npc/magic/level1-magic-blade.txt
@@ -0,0 +1,34 @@
+-|script|magic-blade|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 9) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ set @chiza_component$, "";
+ if (.@level <= 2 && countitem("SharpKnife") >= 1) set @chiza_component$, "SharpKnife";
+ elif (.@level <= 2 && countitem("Knife") >= 1) set @chiza_component$, "Knife";
+ elif (.@level <= 2) end;
+ if (@chiza_component$ != "") delitem @chiza_component$, 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 9;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ overrideattack (@spellpower/15)+10, 1200, 1, ATTACK_ICON_GENERIC, 30, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ set @chiza_str, Str; // do not allow to equip light armor, cast, and then switch to heavy armor to get bonus str
+ end;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 22) != 22) end; // 0x10 | 0x02 | 0x04
+ setarray @melee_dmg[0], if_then_else(@chiza_component$ == "Knife", 40, 60), (@chiza_str + 5);
+ callfunc "melee_damage";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "chiza"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-make-sulphur.txt b/world/map/npc/magic/level1-make-sulphur.txt
new file mode 100644
index 00000000..2d11e5f6
--- /dev/null
+++ b/world/map/npc/magic/level1-make-sulphur.txt
@@ -0,0 +1,24 @@
+-|script|make-sulphur|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 4) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("PileOfAsh") >= 1) delitem "PileOfAsh", 1; else end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 4; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 4;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/100)+1+(rand(max(1,(800-@spellpower)))/180), 50;
+ setarray @create_items$[0], "SulphurPowder", "PileOfAsh";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "gole"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-summon-maggots.txt b/world/map/npc/magic/level1-summon-maggots.txt
new file mode 100644
index 00000000..12d2465c
--- /dev/null
+++ b/world/map/npc/magic/level1-summon-maggots.txt
@@ -0,0 +1,52 @@
+-|script|summon-maggots|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 21) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("MaggotSlime") < 1 || countitem("Root") < 1) end;
+ delitem "MaggotSlime", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 20; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 21;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, ((sqrt(@spellpower)+(@spellpower/15))/5)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, (@spellpower*50)+10000, .@puppet;
+ addnpctimer 5000-(@spellpower*5), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1002, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalmurk"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level1-transmute-wood.txt b/world/map/npc/magic/level1-transmute-wood.txt
new file mode 100644
index 00000000..9984d2b0
--- /dev/null
+++ b/world/map/npc/magic/level1-transmute-wood.txt
@@ -0,0 +1,36 @@
+-|script|spell-transmute-wood|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 5) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("RawLog") >= 1) delitem "RawLog", 1; else end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 4; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 5;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ if (@args$ == "boo") goto L_Mouboo;
+ elif (@args$ == "lurk") goto L_Skytlurk;
+ else message strcharinfo(0), "Magic : ##3##BYou do not know how to transmute wood into this kind of animal."; // FIXME: write a better sentence
+ end;
+
+L_Mouboo:
+ setarray @create_params[0], 1, 40;
+ setarray @create_items$[0], "MoubooFigurine", "WarpedLog";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+L_Skytlurk:
+ if (rand(2) == 1) getitem "Iten", 1;
+ else getitem "WarpedLog", 1;
+ message strcharinfo(0), "Magic : ##3##BYou have no idea what a Skrytlurk looks like.";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "parum"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 1;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-arrow-hail.txt b/world/map/npc/magic/level2-arrow-hail.txt
new file mode 100644
index 00000000..ecd79317
--- /dev/null
+++ b/world/map/npc/magic/level2-arrow-hail.txt
@@ -0,0 +1,112 @@
+-|script|arrow-hail|32767
+{
+ // we can not start here because for the puppets this is OnClick
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (Sp < 25) end;
+ explode .@map_ext[0], getmap(), "-";
+ if (.@map_ext[1] != 1) end; // XXX this is fugly, in the future let's use MF_OUTSIDE to detect if a map is "outside" or "inside"
+ if (getmapflag(getmap(), MF_TOWN)) end;
+ if (countitem("Arrow") >= 20 && countitem("SulphurPowder") >= 1) delitem "Arrow", 20;
+ elif (countitem("IronArrow") >= 20 && countitem("SulphurPowder") >= 1) delitem "IronArrow", 20;
+ else end;
+ delitem "SulphurPowder", 1;
+ set Sp, Sp - 25;
+ set MAGIC_CAST_TICK, gettimetick(2) + 5; // set the new debuff
+
+ setarray @away[0], POS_X, POS_Y, getdir(), (.range + 1), 0;
+ callsub S_AwayFrom;
+
+ set @nearby, 0;
+ foreach 1, getmap(), @away[0] - 14, @away[1] - 14, @away[0] + 14, @away[1] + 14,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ if (@nearby) goto L_Absorb;
+
+ callfunc "adjust_spellpower";
+ set @new_npc_name$, "#" + strnpcinfo(0) + "#" + getcharid(3); // make a unique puppet name for every player
+ callfunc "magic_exp";
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ set @spell_npc, puppet(getmap(), POS_X, POS_Y, @new_npc_name$, 127); // clone npc => get puppet id
+ set .max_hit, (@spellpower / 8), @spell_npc; // set .max_hit in the puppet
+ set .caster, getcharid(3), @spell_npc; // tell the puppet who controls it
+ set .damage, 125, @spell_npc;
+ set .damage_bonus, (@spellpower / 5), @spell_npc;
+ set .area_x, @away[0], @spell_npc; set .area_y, @away[1], @spell_npc;
+ donpcevent @new_npc_name$+"::OnLaunch"; // start the puppet timer and strike
+ initnpctimer @new_npc_name$; // start the destroy timer
+ end;
+
+S_AwayFrom:
+ if(@away[2] == 6 && !(iscollision(getmap(), (@away[0] + 1), @away[1]))) // right
+ set @away[0], @away[0] + 1;
+ if(@away[2] == 4 && !(iscollision(getmap(), @away[0], (@away[1] - 1)))) // up
+ set @away[1], @away[1] - 1;
+ if(@away[2] == 2 && !(iscollision(getmap(), (@away[0] - 1), @away[1]))) // left
+ set @away[0], @away[0] - 1;
+ if(@away[2] == 0 && !(iscollision(getmap(), @away[0], (@away[1] + 1)))) // down
+ set @away[1], @away[1] + 1;
+ set @away[4], @away[4] + 1;
+ if(@away[4] < @away[3]) goto S_AwayFrom;
+ return;
+
+L_Absorb:
+ message strcharinfo(0), "##3Arrow Hail : ##BA nearby arrow hail absorbs your magic!";
+ end;
+
+OnNearbyNpc:
+ explode .@nearby$[0], strnpcinfo(0,@target_id), "#";
+ if(.@nearby$[0] == "arrow-hail" || .@nearby$[1] == "arrow-hail")
+ set @nearby, @nearby + 1;
+ end;
+
+OnLaunch:
+ if(attachrid(.caster) != 1) destroy; // destroy if caster is missing
+ if(getmap() != strnpcinfo(3)) destroy; // destroy if caster left the map
+ set .hit, .hit + 1;
+ if(.hit > .max_hit) destroy;
+ set .launch, 0;
+ callsub S_Launch;
+ addnpctimer 250 + rand(50) + rand(50), strnpcinfo(0)+"::OnLaunch"; // loop until max
+ end;
+
+S_Launch:
+ npcareawarp .area_x - 6, .area_y - 6, .area_x + 6, .area_y + 6, 0, strnpcinfo(0);
+ misceffect FX_ARROW_HAIL;
+ set .done, 0;
+ foreach 3, strnpcinfo(3), getnpcx(), getnpcy(), getnpcx(), getnpcy(), strnpcinfo(0) + "::OnHit";
+ if(!.done && getx() == getnpcx() && gety() == getnpcy())
+ heal 0 - (.damage + rand(.damage_bonus) + rand(.damage_bonus)), 0; // injure caster
+ set .launch, .launch + 1;
+ if(.launch < 3) goto S_Launch;
+ return;
+
+OnTimer30000:
+ debugmes "frillyar timeout! [this shouldn't happen]";
+ destroy;
+
+OnHit:
+ if(attachrid(.caster) != 1) destroy; // destroy if caster is missing
+ if(getmap() != strnpcinfo(3)) destroy; // destroy if caster left the map
+
+ if(target(.caster, @target_id, 16) != 16 && .caster != @target_id) end;
+ if((get(BL_TYPE, @target_id) & 1) == 0) end; // either mob or pc
+ set .@damage, .damage + rand(.damage_bonus) + rand(.damage_bonus);
+ if(.caster != @target_id)
+ set .@damage, (.@damage * (100 - get(MDEF1, @target_id))) / 100;
+ injure .caster, @target_id, .@damage;
+ set .done, 1;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_WAR;
+ set .range, 7;
+ set .invocation$, chr(MAGIC_SYMBOL) + "frillyar"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-barrier.txt b/world/map/npc/magic/level2-barrier.txt
new file mode 100644
index 00000000..89a50044
--- /dev/null
+++ b/world/map/npc/magic/level2-barrier.txt
@@ -0,0 +1,48 @@
+-|script|magic-barrier|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 15) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("SmallMushroom") >= 1) delitem "SmallMushroom", 1;
+ elif (.@level <= 3) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+
+ set @asorm_caster, BL_ID, @target_id;
+ if (attachrid(@target_id) != 1) end;
+ set @target_hat, getequipid(equip_head), @asorm_caster;
+ if (attachrid(@asorm_caster) != 1) end;
+ if (@target_hat == 888) end; // FIXME: this whole 5 line block could be done with only one line if we modify getequipid
+
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 15;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ if (BL_ID != @target_id) misceffect FX_MAGIC_DEFAULT, @args$;
+ set .@time, (@spellpower*200)+2000;
+ set @asorm_time, .@time, @target_id;
+ sc_start SC_MBARRIER, .@time, max(30,(@spellpower/8))+20, @target_id;
+ message @args$, "Barrier : You are surrounded by a magical barrier.";
+ if (attachrid(@target_id) != 1) end;
+ addtimer @asorm_time, strnpcinfo(0)+"::OnEnd";
+ end;
+
+OnEnd:
+ message strcharinfo(0), "Barrier : Your magical barrier dissipates.";
+ misceffect FX_MAGIC_DEFAULT, strcharinfo(0);
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "asorm"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 3;
+ end;
+}
diff --git a/world/map/npc/magic/level2-detect-players.txt b/world/map/npc/magic/level2-detect-players.txt
new file mode 100644
index 00000000..3b024d38
--- /dev/null
+++ b/world/map/npc/magic/level2-detect-players.txt
@@ -0,0 +1,32 @@
+-|script|detect-players|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 7) end;
+ if (getskilllv(.school) < .level) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // XXX the casttime is 300 so should this be 0 ?
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 7;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ callfunc "magic_exp";
+ set @inwilt$, "";
+ set .@d, @spellpower/2;
+ foreach 0, getmap(), POS_X - .@d, POS_Y - .@d, POS_X + .@d, POS_Y + .@d, strnpcinfo(0)+"::OnPC";
+ message strcharinfo(0), if_then_else(@inwilt$=="", "You sense no-one else nearby.", "You sense the following: "+@inwilt$);
+ end;
+
+OnPC:
+ if (@target_id == BL_ID) end; // do not count the caster
+ if (sc_check(SC_HIDE, @target_id)) end; // do not count players with anwiltyp
+ if (getpvpflag(1, @target_id)) end; // do not count invisible players
+ if (@inwilt$ != "") set @inwilt$, @inwilt$ + ", ";
+ set @inwilt$, @inwilt$ + strcharinfo(0, @target_id) + if_then_else(@spellpower > 99, "("+get(BaseLevel, @target_id)+")", "");
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "inwilt"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/level2-enchant-lifestone.txt b/world/map/npc/magic/level2-enchant-lifestone.txt
new file mode 100644
index 00000000..9d56f84a
--- /dev/null
+++ b/world/map/npc/magic/level2-enchant-lifestone.txt
@@ -0,0 +1,35 @@
+-|script|enchant-lifestone|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 15) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("BugLeg") >= 1) delitem "BugLeg", 1;
+ elif (countitem("MaggotSlime") >= 1) delitem "MaggotSlime", 1;
+ elif (countitem("MauveHerb") >= 1 && countitem("AlizarinHerb") >= 1 && countitem("CobaltHerb") >= 1 && countitem("GambogeHerb") >= 1) goto L_Herbs;
+ else end;
+ goto L_Proceed;
+
+L_Herbs:
+ delitem "MauveHerb", 1;
+ delitem "AlizarinHerb", 1;
+ delitem "CobaltHerb", 1;
+ delitem "GambogeHerb", 1;
+ goto L_Proceed;
+
+L_Proceed:
+ set MAGIC_CAST_TICK, gettimetick(2) + 4; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 15;
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ getitem "Lifestone", 1;
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC;
+ set .invocation$, chr(MAGIC_SYMBOL) + "manpahil"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-flying-backpack.txt b/world/map/npc/magic/level2-flying-backpack.txt
new file mode 100644
index 00000000..f2ab0b07
--- /dev/null
+++ b/world/map/npc/magic/level2-flying-backpack.txt
@@ -0,0 +1,39 @@
+-|script|flying-backpack|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 12) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("SilkCocoon") >= 1) delitem "SilkCocoon", 1;
+ elif (.@level <= 3) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 12;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID != @target_id) misceffect FX_MAGIC_GENERIC, @args$;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ set @plugh_time, (@spellpower*500)+5000, @target_id;
+ sc_start SC_FLYING_BACKPACK, @plugh_time, 0, @target_id;
+ message @args$, "Backpack : Your backpack is lifted by a mystical force; you no longer feel it pressing on your back.";
+ if (attachrid(@target_id) != 1) end;
+ addtimer @plugh_time, strnpcinfo(0)+"::OnEnd";
+ end;
+
+OnEnd:
+ message strcharinfo(0), "Backpack : Your backpack is no longer levitating.";
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "plugh"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-happy-curse.txt b/world/map/npc/magic/level2-happy-curse.txt
new file mode 100644
index 00000000..0ad2d113
--- /dev/null
+++ b/world/map/npc/magic/level2-happy-curse.txt
@@ -0,0 +1,42 @@
+-|script|happy-curse|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 13) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("GingerBreadMan") >= 1) delitem "GingerBreadMan", 1;
+ elif (.@level <= 3) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 13;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/100)+1) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ set @joyplim_count, 1, @target_id;
+ set @joyplim_emote, if_then_else(getskilllv(SKILL_MAGIC_DARK) > 1, EMOTE_EVIL, EMOTE_HAPPY), @target_id;
+ set @joyplim_total, (@spellpower/10), @target_id;
+ if (attachrid(@target_id) != 1) end;
+ emotion @joyplim_emote, "self";
+ addtimer 500, strnpcinfo(0)+"::OnEmote";
+ end;
+
+OnEmote:
+ emotion @joyplim_emote, "self";
+ set @joyplim_count, @joyplim_count + 1;
+ if (@joyplim_count < @joyplim_total) addtimer 500, strnpcinfo(0)+"::OnEmote";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "joyplim"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-hide.txt b/world/map/npc/magic/level2-hide.txt
new file mode 100644
index 00000000..42de7f6a
--- /dev/null
+++ b/world/map/npc/magic/level2-hide.txt
@@ -0,0 +1,43 @@
+-|script|spell-hide|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 11) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("CottonCloth") >= 1) delitem "CottonCloth", 1;
+ elif (.@level <= 3) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 11;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ if (BL_ID != @target_id) misceffect FX_MAGIC_DEFAULT, @args$;
+ set .@time, (@spellpower*2500)+5000;
+ set @anwiltyp_time, .@time, @target_id;
+ sc_start SC_HIDE, .@time, 0, @target_id;
+ message @args$, "Magic : You are hidden!";
+ if (BL_ID != @target_id) message strcharinfo(0), "Magic : You hid someone!";
+ if (attachrid(@target_id) != 1) end;
+ addtimer @anwiltyp_time, strnpcinfo(0)+"::OnEnd";
+ end;
+
+OnEnd:
+ message strcharinfo(0), "Magic : You are no longer hidden.";
+ misceffect FX_MAGIC_GENERIC, strcharinfo(0);
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "anwiltyp"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-lay-on-hands.txt b/world/map/npc/magic/level2-lay-on-hands.txt
new file mode 100644
index 00000000..d106ac54
--- /dev/null
+++ b/world/map/npc/magic/level2-lay-on-hands.txt
@@ -0,0 +1,57 @@
+-|script|lay-on-hands|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 10) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (@args$ == "Mouboo" || @args$ == "mouboo") goto L_Mouboo;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) end;
+ if (Hp <= get(MaxHp, @target_id) / 20) end; // hp needs to be > 1/20 * target hp
+ callfunc "adjust_spellpower";
+ if (distance(BL_ID, @target_id) >= (((sqrt(@spellpower)*12)+@spellpower)/100)+2) end;
+ if (sc_check(SC_HALT_REGENERATE,@target_id)) end;
+ if (getequipid(equip_head, @args$) == 888) end; // magic gm top hat
+ set .@needed, get(MaxHp, @target_id) - get(Hp, @target_id);
+ goto L_Pay;
+
+L_Pay:
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // XXX should this be 0 ?
+ set Sp, Sp - 10;
+ misceffect FX_MAGIC_WHITE, strcharinfo(0); // on caster
+ misceffect FX_MAGIC_WHITE, @args$; // on target
+
+ set .@fraction, max(80, 200 - (Vit + (@spellpower/10))); // pay at least 40%
+ set .@payment, (.@needed * .@fraction) / 200;
+ set .@available, Hp - (MaxHp / 20);
+ set .@power, if_then_else(.@payment < .@available, .@needed+1-1, (.@available * 200) / .@fraction); // FIXME / XXX why the f do I need to do +1-1 ?
+ if (.@payment > .@available) set .@payment, .@available;
+
+ set @inma_power, .@power, @target_id;
+
+ set @mexp, min(.exp_gain, .@payment/100); // TODO pass this to gain_heal_exp so it can be passed to gain_exp
+ // TODO gain_heal_exp(.@power, 1, 1, 3) => gain_exp
+
+ set .@dark, getskilllv(SKILL_MAGIC_DARK) >= 2; // true if dark magic user
+ set .@bad, (MaxHp/20)*(0-1);
+ if (.@dark) heal .@bad, 0;
+ sc_start SC_HALT_REGENERATE, if_then_else(.@dark, 5000, 10000), 0;
+
+ if (attachrid(@target_id) != 1) end;
+ if (!(isdead())) heal @inma_power, 0;
+ end;
+
+L_Mouboo:
+ set @spell, 1;
+ callfunc "QuestMoubooHeal";
+ set .@needed, 1000;
+ goto L_Pay;
+
+OnInit:
+ set .school, SKILL_MAGIC_LIFE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "inma"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 4; // this is MAX possible exp
+ end;
+}
diff --git a/world/map/npc/magic/level2-lightning-strike.txt b/world/map/npc/magic/level2-lightning-strike.txt
new file mode 100644
index 00000000..d27d88df
--- /dev/null
+++ b/world/map/npc/magic/level2-lightning-strike.txt
@@ -0,0 +1,67 @@
+-|script|lightning-strike|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 20) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (.@level <= 3 && countitem("IronPowder") >= 1) delitem "IronPowder", 1;
+ elif (.@level <= 3) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 20;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ set @ingrav_sp, @spellpower;
+ set @ingrav_luk, Luk;
+ overrideattack (@spellpower/90)+1, 3000, 8, ATTACK_ICON_GENERIC, 31, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ end;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 22) != 22) end; // 0x10 | 0x02 | 0x04
+
+ set @ingrav_rain, 0;
+ set .@p, get(.max_radius, "rain") + 1;
+ set @ingrav_target, @target_id; // store it because foreach overwrites it
+ foreach 1, getmap(), POS_X-.@p, POS_Y-.@p, POS_X+.@p, POS_Y+.@p, strnpcinfo(0)+"::OnNpc";
+ set @target_id, @ingrav_target; // now restore it
+
+ if (@ingrav_rain & 1) goto L_InRain;
+ setarray @edmg[0], @ingrav_sp, (@ingrav_sp/2)+1, ELT_EARTH, ELT_WIND, FX_LIGHTNING1 + rand(3);
+ callfunc "elt_damage";
+ end;
+
+OnNpc:
+ set .@name$, strnpcinfo(0,@target_id);
+ explode .@nearby$[0], .@name$, "#";
+ if (.@nearby$[0] != "rain" && .@nearby$[1] != "rain") end;
+ setarray .@l[0], getnpcx(.@name$), getnpcy(.@name$), get(.radius, @target_id); // kaflosh x, y, radius
+ setarray @ar[0], .@l[0]-.@l[2], .@l[1]-.@l[2], .@l[0]+.@l[2], .@l[1]+.@l[2]; // kaflosh x1, y1, x2, y2 <= this is "area"
+ if (POS_X >= @ar[0] && POS_Y >= @ar[1] && POS_X <= @ar[2] && POS_Y <= @ar[3])
+ set @ingrav_rain, @ingrav_rain | 1;
+ end;
+
+L_InRain:
+ set @used, 0;
+ foreach 3, getmap(), @ar[0], @ar[1], @ar[2], @ar[3], strnpcinfo(0)+"::OnEntityInRain";
+ if (@used >= 1 && (@ingrav_luk + rand(200)) >= 150) end;
+ misceffect FX_LIGHTNING1 + rand(3), strcharinfo(0);
+ heal 0 - @ingrav_sp, 0;
+ end;
+
+OnEntityInRain:
+ if (target(BL_ID, @target_id, 16) != 16) end; // 0x10
+ if (@ingrav_luk + rand(200) <= 175) end;
+ set @used, @used + 1;
+ setarray @edmg[0], @ingrav_sp/6, (((@ingrav_sp/2)+1)/3)+1, ELT_EARTH, ELT_WIND, FX_LIGHTNING1 + rand(3);
+ callfunc "elt_damage";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "ingrav"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-magic-knuckles.txt b/world/map/npc/magic/level2-magic-knuckles.txt
new file mode 100644
index 00000000..76ff3215
--- /dev/null
+++ b/world/map/npc/magic/level2-magic-knuckles.txt
@@ -0,0 +1,32 @@
+-|script|magic-knuckles|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 20) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (.@level <= 3 && countitem("Beer") >= 1) delitem "Beer", 1;
+ elif (.@level <= 3) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 20;
+ misceffect FX_MAGIC_BLACK, strcharinfo(0);
+ overrideattack (@spellpower/10)+10, 1300, 1, ATTACK_ICON_GENERIC, 34, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ set @upmaru_str, Str; // do not allow to equip light armor, cast, and then switch to heavy armor to get bonus str
+ end;
+
+OnAttack:
+ if (target(BL_ID, @target_id, 22) != 22) end; // 0x10 | 0x02 | 0x04
+ setarray @melee_dmg[0], 30, ((@upmaru_str*2) + 5);
+ callfunc "melee_damage";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_WAR;
+ set .invocation$, chr(MAGIC_SYMBOL) + "upmaru"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-make-arrows.txt b/world/map/npc/magic/level2-make-arrows.txt
new file mode 100644
index 00000000..897598f9
--- /dev/null
+++ b/world/map/npc/magic/level2-make-arrows.txt
@@ -0,0 +1,26 @@
+-|script|make-arrows|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 8) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("RawLog") < 1) end;
+ delitem "RawLog", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 5; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 8;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/40)+1+(rand(max(1,(800-@spellpower)))/80), 500;
+ setarray @create_items$[0], "Arrow", "WarpedLog";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kularzufrill"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-make-iron-powder.txt b/world/map/npc/magic/level2-make-iron-powder.txt
new file mode 100644
index 00000000..089150ac
--- /dev/null
+++ b/world/map/npc/magic/level2-make-iron-powder.txt
@@ -0,0 +1,26 @@
+-|script|make-iron-powder|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 8) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("IronOre") < 1) end;
+ delitem "IronOre", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 5; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 8;
+ misceffect FX_MAGIC_RED, strcharinfo(0);
+ setarray @create_params[0], (@spellpower/140)+1+(rand(max(1,(900-@spellpower)))/220), 700;
+ setarray @create_items$[0], "IronPowder", "IronOre";
+ callfunc "magic_create_item";
+ callfunc "magic_exp";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_TRANSMUTE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "zukminbirf"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 3;
+ end;
+}
diff --git a/world/map/npc/magic/level2-protect.txt b/world/map/npc/magic/level2-protect.txt
new file mode 100644
index 00000000..e4ca8d76
--- /dev/null
+++ b/world/map/npc/magic/level2-protect.txt
@@ -0,0 +1,48 @@
+-|script|protect|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 14) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (.@level <= 3 && countitem("HardSpike") >= 1) delitem "HardSpike", 1;
+ elif (.@level <= 3) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) set @target_id, BL_ID; // fallback to self
+
+ set @betsanc_caster, BL_ID, @target_id;
+ if (attachrid(@target_id) != 1) end;
+ set @target_hat, getequipid(equip_head), @betsanc_caster;
+ if (attachrid(@betsanc_caster) != 1) end;
+ if (@target_hat == 888) end; // FIXME: this whole 5 line block could be done with only one line if we modify getequipid
+
+ set MAGIC_CAST_TICK, gettimetick(2) + 2; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 14;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ callfunc "magic_exp";
+
+ if (distance(BL_ID, @target_id) >= (@spellpower/30)+2) set @target_id, BL_ID;
+ if (BL_ID == @target_id) set @args$, strcharinfo(0);
+ misceffect FX_MAGIC_SHIELD, @args$;
+ set .@time, (@spellpower*1000)+5000;
+ set @betsanc_time, .@time, @target_id;
+ sc_start SC_PHYS_SHIELD, .@time, max(15,(@spellpower/20))+5, @target_id;
+ message @args$, "Shield : You feel more protected.";
+ if (attachrid(@target_id) != 1) end;
+ addtimer @betsanc_time, strnpcinfo(0)+"::OnEnd";
+ end;
+
+OnEnd:
+ message strcharinfo(0), "Shield : You feel less protected.";
+ misceffect FX_MAGIC_SHIELD_ENDS, strcharinfo(0);
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "betsanc"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-rain.txt b/world/map/npc/magic/level2-rain.txt
new file mode 100644
index 00000000..f12c9072
--- /dev/null
+++ b/world/map/npc/magic/level2-rain.txt
@@ -0,0 +1,103 @@
+-|script|rain|32767
+{
+ // we can not start here because for the puppets this is OnClick
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (Sp < 17) end;
+ explode .@map_ext[0], getmap(), "-";
+ if (.@map_ext[1] != 1) end; // XXX this is fugly, in the future let's use MF_OUTSIDE to detect if a map is "outside" or "inside"
+ if (getmapflag(getmap(), MF_TOWN)) end;
+ if (getskilllv(.school) < 4 && countitem("BottleOfWater") >= 1) delitem "BottleOfWater", 1;
+ elif (getskilllv(.school) < 4) end;
+ set Sp, Sp - 17;
+ set MAGIC_CAST_TICK, gettimetick(2) + 3; // set the new debuff
+
+ callfunc "adjust_spellpower";
+ set @krad, min(.max_radius,(min(@spellpower,200)/30)+3); // kaflosh radius
+
+ set @nearby, 0;
+ foreach 1, getmap(), POS_X - .max_radius, POS_Y - .max_radius, POS_X + .max_radius, POS_Y + .max_radius,
+ strnpcinfo(0) + "::OnNearbyNpc";
+ if (@nearby) goto L_Absorb;
+
+ set @new_npc_name$, "#" + strnpcinfo(0) + "#" + getcharid(3); // make a unique puppet name for every player
+ callfunc "magic_exp";
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ set @spell_npc, puppet(getmap(), POS_X, POS_Y, @new_npc_name$, 127); // clone npc => get puppet id
+ set .caster, getcharid(3), @spell_npc; // tell the puppet who controls it
+ set .radius, @krad, @spell_npc; // this is also used by ingrav, don't rename
+ set .initial_x, POS_X, @spell_npc;
+ set .initial_y, POS_Y, @spell_npc;
+ set .max, @spellpower/3, @spell_npc;
+ set .max_launch, min(200,@spellpower/2)/100, @spell_npc;
+ donpcevent @new_npc_name$+"::OnLaunch"; // start
+ addnpctimer 30000, @new_npc_name$+"::OnDestroy"; // this is just a failsafe in case the npc is not properly destroyed
+ if(isin("011-1", 85, 31, 103, 45)) goto L_Pumpkins;
+ end;
+
+L_Absorb:
+ message strcharinfo(0), "##3Rain : ##BA nearby raincloud absorbs your magic.";
+ end;
+
+OnNearbyNpc:
+ explode .@nearby$[0], strnpcinfo(0,@target_id), "#";
+ if(.@nearby$[1] == "DruidTree0" || .@nearby$[1] == "DruidTree0") goto L_Tree;
+ if(.@nearby$[0] == "rain" || .@nearby$[1] == "rain")
+ set @nearby, @nearby + 1;
+ end;
+
+L_Pumpkins:
+ callfunc "HalloweenQuestWaterPumpkins";
+ end;
+
+L_Tree:
+ set .@x, get(POS_X, @target_id); set .@y, get(POS_Y, @target_id);
+ if (.@x < POS_X-@krad || .@y < POS_Y-@krad || .@x > POS_X+@krad || .@y > POS_Y+@krad) end; // in max radius but not in puppet area
+ set @flag, 1;
+ callfunc "QuestTreeTrigger";
+ close;
+
+OnLaunch:
+ if(attachrid(.caster) != 1) destroy; // destroy if caster is missing
+ if(getmap() != strnpcinfo(3)) destroy; // destroy if caster left the map
+ set .count, .count + 1;
+ if(.count > .max) destroy;
+ set .launch, 0;
+ callsub S_Launch;
+ addnpctimer 400 + rand(100), strnpcinfo(0)+"::OnLaunch"; // loop until max
+ end;
+
+S_Launch:
+ npcareawarp .initial_x - .radius, .initial_y - .radius, .initial_x + .radius, .initial_y + .radius, 0, strnpcinfo(0);
+ misceffect FX_RAIN;
+ foreach 3, strnpcinfo(3), getnpcx()-1, getnpcy()-1, getnpcx()+1, getnpcy()+1, strnpcinfo(0) + "::OnHit";
+ set .launch, .launch + 1;
+ if(.launch < .max_launch) goto S_Launch;
+ return;
+
+OnHit:
+ if(attachrid(.caster) != 1) destroy; // destroy if caster is missing
+ if(getmap() != strnpcinfo(3)) destroy; // destroy if caster left the map
+ if(target(.caster, @target_id, 16) != 16 && .caster != @target_id) end;
+ if((get(BL_TYPE, @target_id) & 1) == 0) end; // either mob or pc
+ if(elttype(@target_id) == ELT_FIRE)
+ injure .caster, @target_id, rand((@spellpower/15)+5)+2;
+ end;
+
+OnDestroy:
+ debugmes "kaflosh timeout! [this shouldn't happen]";
+ destroy;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kaflosh"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 1;
+ set .max_radius, 15;
+ end;
+}
diff --git a/world/map/npc/magic/level2-shear.txt b/world/map/npc/magic/level2-shear.txt
new file mode 100644
index 00000000..5af782e1
--- /dev/null
+++ b/world/map/npc/magic/level2-shear.txt
@@ -0,0 +1,49 @@
+-|script|shear|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 23) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 23;
+ misceffect FX_MAGIC_GREEN, strcharinfo(0);
+ overrideattack 1, 2000, 1, ATTACK_ICON_SHEARING, 30, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ set @chipchip_sp, @spellpower;
+ end;
+
+OnAttack:
+ if (isloggedin(@target_id)) end; // can not shear a player
+ if (sc_check(SC_SHEARED, @target_id)) end; // mob already sheared
+ if (target(BL_ID, @target_id, 22) != 22) end; // 0x10 | 0x02 | 0x04
+ sc_start SC_SHEARED, 600000, 0, @target_id;
+ set .@score, rand(1000 - rand(@chipchip_sp));
+ set .@id, get(Class, @target_id); // get the mob ID
+
+ if (.@id == 1020 && .@score < 300) set .@item$, "WhiteFur"; // Fluffy
+ elif (.@id == 1027 && .@score < 300) set .@item$, "WhiteFur"; // EasterFluffy
+ elif (.@id == 1019 && .@score < 250) set .@item$, "HardSpike"; // SpikyMushroom
+ elif (.@id == 1028 && .@score < 175) set .@item$, "CottonCloth"; // Mouboo
+ elif (.@id == 1029 && .@score < 700) set .@item$, "MauveHerb"; // MauvePlant
+ elif (.@id == 1030 && .@score < 700) set .@item$, "CobaltHerb"; // CobaltPlant
+ elif (.@id == 1031 && .@score < 700) set .@item$, "GambogeHerb"; // GambogePlant
+ elif (.@id == 1032 && .@score < 700) set .@item$, "AlizarinHerb"; // AlizarinPlant
+ elif (.@id == 1035 && .@score < 300) set .@item$, "SilkCocoon"; // SilkWorm
+ elif (.@id == 1018 && .@score < 180) set .@item$, "PinkAntenna"; // Pinkie
+ else end;
+ makeitem .@item$, 1, getmap(), rand(POS_X - 1, POS_X + 1), rand(POS_Y - 1, POS_Y + 1);
+
+ if (.@id != 1020 && .@id != 1028 && .@id != 1018 && rand(2) != 1) end;
+ set @value, 1;
+ callfunc "QuestSagathaHappy";
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_NATURE;
+ set .invocation$, chr(MAGIC_SYMBOL) + "chipchip"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 0;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-fluffies.txt b/world/map/npc/magic/level2-summon-fluffies.txt
new file mode 100644
index 00000000..9590b468
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-fluffies.txt
@@ -0,0 +1,53 @@
+-|script|fluffies|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 39) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("WhiteFur") < 1 || countitem("Root") < 1) end;
+ delitem "WhiteFur", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 20; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 39;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/170)+1+(@spellpower/430), .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*350, .@puppet;
+ addnpctimer 5000-(@spellpower*8), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1020, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalakarenk"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-mouboo.txt b/world/map/npc/magic/level2-summon-mouboo.txt
new file mode 100644
index 00000000..6b82b8c9
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-mouboo.txt
@@ -0,0 +1,53 @@
+-|script|mouboos|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("MoubooFigurine") < 1 || countitem("Root") < 1) end;
+ delitem "MoubooFigurine", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 20; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 35;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/270)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*100, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1028, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalboo"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-pinkie.txt b/world/map/npc/magic/level2-summon-pinkie.txt
new file mode 100644
index 00000000..2c8d235e
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-pinkie.txt
@@ -0,0 +1,53 @@
+-|script|pinkies|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("PinkAntenna") < 1 || countitem("Root") < 1) end;
+ delitem "PinkAntenna", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 20; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 35;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/120)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*150, .@puppet;
+ addnpctimer 5000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1018, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalgina"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 2;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-snakes.txt b/world/map/npc/magic/level2-summon-snakes.txt
new file mode 100644
index 00000000..2bce0f96
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-snakes.txt
@@ -0,0 +1,54 @@
+-|script|summon-snakes|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 40) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("DarkCrystal") < 1 || countitem("SnakeEgg") < 1) end;
+ if (OrumQuest <= 40) end;
+ delitem "DarkCrystal", 1;
+ delitem "SnakeEgg", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 15; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 40;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/300)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*80, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1010, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "halhiss"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 3;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-spiky-mushroom.txt b/world/map/npc/magic/level2-summon-spiky-mushroom.txt
new file mode 100644
index 00000000..182bbda5
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-spiky-mushroom.txt
@@ -0,0 +1,53 @@
+-|script|spikymushroom|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 33) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("HardSpike") < 1 || countitem("Root") < 1) end;
+ delitem "HardSpike", 1;
+ delitem "Root", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 20; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 33;
+ misceffect FX_MAGIC_BLUE, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/120)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*400, .@puppet;
+ addnpctimer 5000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1019, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_ASTRAL;
+ set .invocation$, chr(MAGIC_SYMBOL) + "kalrenk"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/magic/level2-summon-wickedmushroom.txt b/world/map/npc/magic/level2-summon-wickedmushroom.txt
new file mode 100644
index 00000000..bceef8b6
--- /dev/null
+++ b/world/map/npc/magic/level2-summon-wickedmushroom.txt
@@ -0,0 +1,54 @@
+-|script|wickedmushroom|32767
+{
+ end;
+
+OnCast:
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 35) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ if (getskilllv(.school) < .level) end;
+ if (countitem("DarkCrystal") < 1 || countitem("SmallMushroom") < 1) end;
+ if (OrumQuest <= 36) end;
+ delitem "DarkCrystal", 1;
+ delitem "SmallMushroom", 1;
+ set MAGIC_CAST_TICK, gettimetick(2) + 15; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 35;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ misceffect FX_PENTAGRAM_BUILDUP, strcharinfo(0);
+ callfunc "magic_exp";
+ set .@puppet$, "#"+strnpcinfo(0)+"#"+BL_ID;
+ set .@puppet, puppet(getmap(), POS_X, POS_Y, .@puppet$, 127);
+ set .count, (@spellpower/250)+1, .@puppet;
+ set .master, BL_ID, .@puppet;
+ set .lifetime, @spellpower*80, .@puppet;
+ addnpctimer 4000-(@spellpower*9), .@puppet$+"::OnSummon";
+ addnpctimer 6000, .@puppet$+"::OnDestroy";
+ end;
+
+OnSummon:
+ specialeffect FX_PENTAGRAM_BURST;
+ set .@i, 0;
+ set .@x, getnpcx();
+ set .@y, getnpcy();
+ set .@map$, strnpcinfo(3);
+ callsub S_SummonAll;
+ end;
+
+OnDestroy:
+ destroy;
+
+S_SummonAll:
+ summon .@map$, rand(.@x-2,.@x+2), rand(.@y-2,.@y+2), .master, 1106, 2, .lifetime;
+ set .@i, .@i + 1;
+ if (.@i < .count) goto S_SummonAll;
+ return;
+
+OnInit:
+ set .school, SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "helorp"; // used in npcs that refer to this spell
+ callfunc "magic_register2";
+ set .level, 2;
+ set .exp_gain, 3;
+ end;
+}
diff --git a/world/map/npc/magic/level2-toxic-dart.txt b/world/map/npc/magic/level2-toxic-dart.txt
new file mode 100644
index 00000000..91522a58
--- /dev/null
+++ b/world/map/npc/magic/level2-toxic-dart.txt
@@ -0,0 +1,36 @@
+-|script|toxic-dart|32767
+{
+ callfunc "magic_checks"; if(@failed) end; // << I wish we had functions that could return >>
+ if (Sp < 15) end;
+ set .@level, getskilllv(.school);
+ if (.@level < .level) end;
+ if (OrumQuest <= 37) end;
+ if (.@level <= 2 && countitem("Root") >= 2) delitem "Root", 2;
+ elif (.@level <= 2) end;
+ set MAGIC_CAST_TICK, gettimetick(2) + 1; // set the new debuff
+ callfunc "adjust_spellpower";
+ set Sp, Sp - 15;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ set @damage, sqrt(@spellpower) * 5;
+ set @dmg_bonus, (BaseLevel/3) + 5;
+ overrideattack (@spellpower/75)+3, 1200, 4, ATTACK_ICON_GENERIC, 31, strnpcinfo(0)+"::OnAttack";
+ callfunc "magic_exp";
+ end;
+
+OnAttack:
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0);
+ if (target(BL_ID, @target_id, 50) != 50) end; // 0x20 | 0x02 | 0x10
+ setarray @edmg[0], @damage, @dmg_bonus, ELT_NEUTRAL, ELT_POISON, FX_FIRE_BURST;
+ callfunc "elt_damage";
+ if(@target_id != BL_ID && isloggedin(@target_id)) // this is a dirty trick to check if the target is a player
+ sc_start sc_poison, 5000+(@spellpower*1200), max(15,@spellpower/15)+5, @target_id;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "phlex"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 2;
+ set .exp_gain, 3;
+ end;
+}
diff --git a/world/map/npc/magic/level3-necromancy.txt b/world/map/npc/magic/level3-necromancy.txt
new file mode 100644
index 00000000..bd1f611c
--- /dev/null
+++ b/world/map/npc/magic/level3-necromancy.txt
@@ -0,0 +1,54 @@
+// see https://tmworld.uservoice.com/forums/255809-general/suggestions/6051818-sacrifice
+// author: gumi
+-|script|necromancy|32767
+{
+ callfunc "magic_checks"; if(@failed) end;
+ if (Sp < 50) end;
+ if (getskilllv(.school) < .level) end;
+ if (getskilllv(SKILL_MAGIC) < .level) end;
+ set @target_id, getcharid(3, @args$);
+ if (@target_id < 1 || !(isloggedin(@target_id))) end;
+ if (get(Hp, @target_id) > 0) end;
+ if (Hp < (get(MaxHp, @target_id) / 3)) end; // hp must be at least a third of the max hp of the target
+ callfunc "adjust_spellpower";
+ if (distance(BL_ID, @target_id) >= (((sqrt(@spellpower)*12)+@spellpower)/100)+2) end;
+ if (get(@necromancer, @target_id) > 0) end; // someone else is already trying to resurrect this player
+ if (getmapflag(getmap(), MF_NOSAVE)) end; // do not allow for maps like illia or candor
+ if (countitem("Soul") >= 1) delitem "Soul", 1; else end;
+
+ set MAGIC_CAST_TICK, gettimetick(2) + 20;
+ set Sp, Sp - 50;
+ misceffect FX_MAGIC_DARKRED, strcharinfo(0); // on caster
+ misceffect FX_PENTAGRAM_BUILDUP, @args$; // on target
+
+ set @necromancer, CHAR_ID, @target_id; // tell the target who is reviving them
+
+ if (attachrid(@target_id) != 1) end;
+ addtimer 6000, strnpcinfo(0)+"::OnRevive"; // TODO: make it take more or less time depending on the spell power
+ end;
+
+OnRevive:
+ set .@necro, get(BL_ID, @necromancer);
+ if (.@necro < 1) goto L_Clean;
+ if (get(Hp, .@necro) < 1) end;
+ misceffect FX_PENTAGRAM_BURST, strcharinfo(0);
+ misceffect FX_CRITICAL, strcharinfo(0, .@necro);
+ heal 1, 0; // revive
+ set Hp, 1;
+ set Sp, 0;
+ set Hp, 1, .@necro;
+ set Sp, 0, .@necro;
+ goto L_Clean;
+
+L_Clean:
+ set @necromancer, 0;
+ end;
+
+OnInit:
+ set .school, SKILL_MAGIC_DARK;
+ set .invocation$, chr(MAGIC_SYMBOL) + "nevela"; // used in npcs that refer to this spell
+ callfunc "magic_register";
+ set .level, 3;
+ set .exp_gain, 1;
+ end;
+}
diff --git a/world/map/npc/scripts.conf b/world/map/npc/scripts.conf
index e9bceb20..68a348e1 100644
--- a/world/map/npc/scripts.conf
+++ b/world/map/npc/scripts.conf
@@ -32,6 +32,7 @@ npc: npc/functions/dynamic_menu.txt
npc: npc/functions/DyeConfig.txt
npc: npc/functions/motd.txt
npc: npc/functions/motdconfig.txt
+npc: npc/functions/hug.txt
// Item Functions
npc: npc/items/magic_gm_top_hat.txt
@@ -50,6 +51,12 @@ npc: npc/items/mirror.txt
npc: npc/items/rubber_bat.txt
import: npc/_import.txt
+// magic
+import: npc/magic/_import.txt
+
+// GM commands
+import: npc/commands/_import.txt
+
// GM Events
npc: npc/functions/gm_island.txt
// Annuals Framework