summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/core/util.lua7
-rw-r--r--lib/mods/theme/core/util.lua7
-rw-r--r--lib/mods/theme/scpt/s_meta.lua203
-rw-r--r--lib/scpt/s_meta.lua203
-rw-r--r--src/birth.c4
-rw-r--r--src/dungeon.c9
-rw-r--r--src/externs.h24
-rw-r--r--src/init2.c5
-rw-r--r--src/loadsave.c32
-rw-r--r--src/lua_bind.c2
-rw-r--r--src/player.pkg16
-rw-r--r--src/spells.pkg49
-rw-r--r--src/spells3.c310
-rw-r--r--src/types.h6
-rw-r--r--src/util.c19
-rw-r--r--src/xtra1.c2
16 files changed, 445 insertions, 453 deletions
diff --git a/lib/core/util.lua b/lib/core/util.lua
index eea13014..048b0d0f 100644
--- a/lib/core/util.lua
+++ b/lib/core/util.lua
@@ -93,13 +93,6 @@ function new_timer(t)
return timer
end
--- saves all timer values
-function save_timer(name)
- add_loadsave(name..".enabled", FALSE)
- add_loadsave(name..".delay", 1)
- add_loadsave(name..".countdown", 1)
-end
-
-- displays a scrolling list
function display_list(y, x, h, w, title, list, begin, sel, sel_color)
diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua
index eea13014..048b0d0f 100644
--- a/lib/mods/theme/core/util.lua
+++ b/lib/mods/theme/core/util.lua
@@ -93,13 +93,6 @@ function new_timer(t)
return timer
end
--- saves all timer values
-function save_timer(name)
- add_loadsave(name..".enabled", FALSE)
- add_loadsave(name..".delay", 1)
- add_loadsave(name..".countdown", 1)
-end
-
-- displays a scrolling list
function display_list(y, x, h, w, title, list, begin, sel, sel_color)
diff --git a/lib/mods/theme/scpt/s_meta.lua b/lib/mods/theme/scpt/s_meta.lua
index eab691d8..9040e3af 100644
--- a/lib/mods/theme/scpt/s_meta.lua
+++ b/lib/mods/theme/scpt/s_meta.lua
@@ -8,25 +8,13 @@ RECHARGE = add_spell
["mana"] = 10,
["mana_max"] = 100,
["fail"] = 20,
- ["spell"] = function()
- return recharge(60 + get_level(RECHARGE, 140))
- end,
- ["info"] = function()
- return "power "..(60 + get_level(RECHARGE, 140))
- end,
+ ["spell"] = function() return meta_recharge() end,
+ ["info"] = function() return meta_recharge_info() end,
["desc"] = {
"Taps on the ambient mana to recharge an object's power (charges or mana)",
}
}
-function get_spellbinder_max()
- local i
-
- i = get_level(SPELLBINDER, 4)
- if i > 4 then i = 4 end
- return i
-end
---'
SPELLBINDER = add_spell
{
["name"] = "Spellbinder",
@@ -35,63 +23,8 @@ SPELLBINDER = add_spell
["mana"] = 100,
["mana_max"] = 300,
["fail"] = 85,
- ["spell"] = function()
- local i, ret, c
-
- if player.spellbinder_num ~= 0 then
- local t =
- {
- [SPELLBINDER_HP75] = "75% HP",
- [SPELLBINDER_HP50] = "50% HP",
- [SPELLBINDER_HP25] = "25% HP",
- }
- msg_print("The spellbinder is already active.")
- msg_print("It will trigger at "..t[player.spellbinder_trigger]..".")
- msg_print("With the spells: ")
- for i = 1, player.spellbinder_num do
- msg_print(spell(player.spellbinder[i]).name)
- end
- return TRUE
- end
-
- ret, c = get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", strbyte("a"))
- if ret == FALSE then return TRUE end
-
- if c == strbyte("a") then
- player.spellbinder_trigger = SPELLBINDER_HP75
- elseif c == strbyte("b") then
- player.spellbinder_trigger = SPELLBINDER_HP50
- elseif c == strbyte("c") then
- player.spellbinder_trigger = SPELLBINDER_HP25
- else
- return
- end
- player.spellbinder_num = get_spellbinder_max()
- i = player.spellbinder_num
- while i > 0 do
- local s
-
- s = get_school_spell("bind", "is_ok_spell", 0)
- if s == -1 then
- player.spellbinder_trigger = 0
- player.spellbinder_num = 0
- return TRUE
- else
- if spell(s).skill_level > 7 + get_level(SPELLBINDER, 35) then
- msg_print("You are only allowed spells with a base level of "..(7 + get_level(SPELLBINDER, 35))..".");
- return TRUE
- end
- end
- player.spellbinder[i] = s
- i = i - 1
- end
- player.energy = player.energy - 3100;
- msg_print("Spellbinder ready.")
- return TRUE
- end,
- ["info"] = function()
- return "number "..(get_spellbinder_max()).." max level "..(7 + get_level(SPELLBINDER, 35))
- end,
+ ["spell"] = function() return meta_spellbinder() end,
+ ["info"] = function() return meta_spellbinder_info() end,
["desc"] = {
"Stores spells in a trigger.",
"When the condition is met all spells fire off at the same time",
@@ -125,38 +58,8 @@ DISPERSEMAGIC = add_spell
},
},
["inertia"] = { 1, 5 },
- ["spell"] = function()
- local obvious
- obvious = set_blind(0)
- obvious = is_obvious(set_lite(0), obvious)
- if get_level(DISPERSEMAGIC, 50) >= 5 then
- obvious = is_obvious(set_confused(0), obvious)
- obvious = is_obvious(set_image(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 10 then
- obvious = is_obvious(set_slow(0), obvious)
- obvious = is_obvious(set_fast(0, 0), obvious)
- obvious = is_obvious(set_light_speed(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 15 then
- obvious = is_obvious(set_stun(0), obvious)
- obvious = is_obvious(set_meditation(0), obvious)
- obvious = is_obvious(set_cut(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 20 then
- obvious = is_obvious(set_hero(0), obvious)
- obvious = is_obvious(set_shero(0), obvious)
- obvious = is_obvious(set_blessed(0), obvious)
- obvious = is_obvious(set_shield(0, 0, 0, 0, 0), obvious)
- obvious = is_obvious(set_afraid(0), obvious)
- obvious = is_obvious(set_parasite(0, 0), obvious)
- obvious = is_obvious(set_mimic(0, 0, 0), obvious)
- end
- return TRUE
- end,
- ["info"] = function()
- return ""
- end,
+ ["spell"] = function() return meta_disperse_magic() end,
+ ["info"] = function() return meta_disperse_magic_info() end,
["desc"] = {
"Dispels a lot of magic that can affect you, be it good or bad",
"Level 1: blindness and light",
@@ -175,69 +78,14 @@ TRACKER = add_spell
["mana"] = 50,
["mana_max"] = 50,
["fail"] = 95,
- ["spell"] = function()
- if last_teleportation_y == -1 then
- msg_print("There has not been any teleporatation here.")
- return TRUE
- end
- teleport_player_to(last_teleportation_y, last_teleportation_x)
- return TRUE
- end,
- ["info"] = function()
- return ""
- end,
+ ["spell"] = function() return meta_tracker() end,
+ ["info"] = function() return meta_tracker_info() end,
["desc"] = {
"Tracks down the last teleportation that happened on the level and teleports",
"you to it",
}
}
--- Saves the values of the timer
-save_timer("TIMER_INERTIA_CONTROL")
-add_loadsave("player.inertia_controlled_spell", -1)
-player.inertia_controlled_spell = -1
-
--- Automatically cast the inertia controlled spells
-TIMER_INERTIA_CONTROL = new_timer
-{
- ["enabled"] = FALSE,
- ["delay"] = 10,
- ["callback"] = function()
- -- Don't cast a controlled spell in wilderness mode
- if player.antimagic then
- msg_print("Your anti-magic field disrupts any magic attempts.")
- elseif player.anti_magic then
- msg_print("Your anti-magic shell disrupts any magic attempts.")
- elseif (player.inertia_controlled_spell ~= -1) and (player.wild_mode == FALSE) then
- __spell_spell[player.inertia_controlled_spell]()
- end
- end,
-}
-
-stop_inertia_controlled_spell = function()
- player.inertia_controlled_spell = -1
- TIMER_INERTIA_CONTROL.enabled = FALSE
- player.update = bor(player.update, PU_MANA)
- return TRUE
-end
-
-add_hooks
-{
- -- Reduce the mana by four times the cost of the spell
- [HOOK_CALC_MANA] = function(msp)
- if player.inertia_controlled_spell ~= -1 then
- msp = msp - (get_mana(player.inertia_controlled_spell) * 4)
- if msp < 0 then msp = 0 end
- return TRUE, msp
- end
- end,
-
- -- Stop a previous spell at birth
- [HOOK_BIRTH_OBJECTS] = function()
- stop_inertia_controlled_spell()
- end,
-}
-
INERTIA_CONTROL = add_spell
{
["name"] = "Inertia Control",
@@ -246,39 +94,8 @@ INERTIA_CONTROL = add_spell
["mana"] = 300,
["mana_max"] = 700,
["fail"] = 95,
- ["spell"] = function()
- if player.inertia_controlled_spell ~= -1 then
- msg_print("You cancel your inertia flow control.")
- return stop_inertia_controlled_spell()
- end
-
- local s = get_school_spell("control", "is_ok_spell", 0)
- if s == -1 then
- return stop_inertia_controlled_spell()
- end
-
- local inertia = __tmp_spells[s].inertia
-
- if inertia == nil then
- msg_print("This spell inertia flow can not be controlled.")
- return stop_inertia_controlled_spell()
- end
- if inertia[1] > get_level(INERTIA_CONTROL, 10) then
- msg_print("This spell inertia flow("..inertia[1]..") is too strong to be controlled by your current spell.")
- return stop_inertia_controlled_spell()
- end
-
- player.inertia_controlled_spell = s
- TIMER_INERTIA_CONTROL.enabled = TRUE
- TIMER_INERTIA_CONTROL.delay = inertia[2]
- TIMER_INERTIA_CONTROL.countdown = TIMER_INERTIA_CONTROL.delay
- player.update = bor(player.update, PU_MANA)
- msg_print("Inertia flow controlling spell "..spell(s).name..".")
- return TRUE
- end,
- ["info"] = function()
- return "level "..get_level(INERTIA_CONTROL, 10)
- end,
+ ["spell"] = function() return meta_inertia_control() end,
+ ["info"] = function() return meta_inertia_control_info() end,
["desc"] = {
"Changes the energy flow of a spell to be continuously recasted",
"at a given interval. The inertia controlled spell reduces your",
diff --git a/lib/scpt/s_meta.lua b/lib/scpt/s_meta.lua
index eab691d8..9040e3af 100644
--- a/lib/scpt/s_meta.lua
+++ b/lib/scpt/s_meta.lua
@@ -8,25 +8,13 @@ RECHARGE = add_spell
["mana"] = 10,
["mana_max"] = 100,
["fail"] = 20,
- ["spell"] = function()
- return recharge(60 + get_level(RECHARGE, 140))
- end,
- ["info"] = function()
- return "power "..(60 + get_level(RECHARGE, 140))
- end,
+ ["spell"] = function() return meta_recharge() end,
+ ["info"] = function() return meta_recharge_info() end,
["desc"] = {
"Taps on the ambient mana to recharge an object's power (charges or mana)",
}
}
-function get_spellbinder_max()
- local i
-
- i = get_level(SPELLBINDER, 4)
- if i > 4 then i = 4 end
- return i
-end
---'
SPELLBINDER = add_spell
{
["name"] = "Spellbinder",
@@ -35,63 +23,8 @@ SPELLBINDER = add_spell
["mana"] = 100,
["mana_max"] = 300,
["fail"] = 85,
- ["spell"] = function()
- local i, ret, c
-
- if player.spellbinder_num ~= 0 then
- local t =
- {
- [SPELLBINDER_HP75] = "75% HP",
- [SPELLBINDER_HP50] = "50% HP",
- [SPELLBINDER_HP25] = "25% HP",
- }
- msg_print("The spellbinder is already active.")
- msg_print("It will trigger at "..t[player.spellbinder_trigger]..".")
- msg_print("With the spells: ")
- for i = 1, player.spellbinder_num do
- msg_print(spell(player.spellbinder[i]).name)
- end
- return TRUE
- end
-
- ret, c = get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", strbyte("a"))
- if ret == FALSE then return TRUE end
-
- if c == strbyte("a") then
- player.spellbinder_trigger = SPELLBINDER_HP75
- elseif c == strbyte("b") then
- player.spellbinder_trigger = SPELLBINDER_HP50
- elseif c == strbyte("c") then
- player.spellbinder_trigger = SPELLBINDER_HP25
- else
- return
- end
- player.spellbinder_num = get_spellbinder_max()
- i = player.spellbinder_num
- while i > 0 do
- local s
-
- s = get_school_spell("bind", "is_ok_spell", 0)
- if s == -1 then
- player.spellbinder_trigger = 0
- player.spellbinder_num = 0
- return TRUE
- else
- if spell(s).skill_level > 7 + get_level(SPELLBINDER, 35) then
- msg_print("You are only allowed spells with a base level of "..(7 + get_level(SPELLBINDER, 35))..".");
- return TRUE
- end
- end
- player.spellbinder[i] = s
- i = i - 1
- end
- player.energy = player.energy - 3100;
- msg_print("Spellbinder ready.")
- return TRUE
- end,
- ["info"] = function()
- return "number "..(get_spellbinder_max()).." max level "..(7 + get_level(SPELLBINDER, 35))
- end,
+ ["spell"] = function() return meta_spellbinder() end,
+ ["info"] = function() return meta_spellbinder_info() end,
["desc"] = {
"Stores spells in a trigger.",
"When the condition is met all spells fire off at the same time",
@@ -125,38 +58,8 @@ DISPERSEMAGIC = add_spell
},
},
["inertia"] = { 1, 5 },
- ["spell"] = function()
- local obvious
- obvious = set_blind(0)
- obvious = is_obvious(set_lite(0), obvious)
- if get_level(DISPERSEMAGIC, 50) >= 5 then
- obvious = is_obvious(set_confused(0), obvious)
- obvious = is_obvious(set_image(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 10 then
- obvious = is_obvious(set_slow(0), obvious)
- obvious = is_obvious(set_fast(0, 0), obvious)
- obvious = is_obvious(set_light_speed(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 15 then
- obvious = is_obvious(set_stun(0), obvious)
- obvious = is_obvious(set_meditation(0), obvious)
- obvious = is_obvious(set_cut(0), obvious)
- end
- if get_level(DISPERSEMAGIC, 50) >= 20 then
- obvious = is_obvious(set_hero(0), obvious)
- obvious = is_obvious(set_shero(0), obvious)
- obvious = is_obvious(set_blessed(0), obvious)
- obvious = is_obvious(set_shield(0, 0, 0, 0, 0), obvious)
- obvious = is_obvious(set_afraid(0), obvious)
- obvious = is_obvious(set_parasite(0, 0), obvious)
- obvious = is_obvious(set_mimic(0, 0, 0), obvious)
- end
- return TRUE
- end,
- ["info"] = function()
- return ""
- end,
+ ["spell"] = function() return meta_disperse_magic() end,
+ ["info"] = function() return meta_disperse_magic_info() end,
["desc"] = {
"Dispels a lot of magic that can affect you, be it good or bad",
"Level 1: blindness and light",
@@ -175,69 +78,14 @@ TRACKER = add_spell
["mana"] = 50,
["mana_max"] = 50,
["fail"] = 95,
- ["spell"] = function()
- if last_teleportation_y == -1 then
- msg_print("There has not been any teleporatation here.")
- return TRUE
- end
- teleport_player_to(last_teleportation_y, last_teleportation_x)
- return TRUE
- end,
- ["info"] = function()
- return ""
- end,
+ ["spell"] = function() return meta_tracker() end,
+ ["info"] = function() return meta_tracker_info() end,
["desc"] = {
"Tracks down the last teleportation that happened on the level and teleports",
"you to it",
}
}
--- Saves the values of the timer
-save_timer("TIMER_INERTIA_CONTROL")
-add_loadsave("player.inertia_controlled_spell", -1)
-player.inertia_controlled_spell = -1
-
--- Automatically cast the inertia controlled spells
-TIMER_INERTIA_CONTROL = new_timer
-{
- ["enabled"] = FALSE,
- ["delay"] = 10,
- ["callback"] = function()
- -- Don't cast a controlled spell in wilderness mode
- if player.antimagic then
- msg_print("Your anti-magic field disrupts any magic attempts.")
- elseif player.anti_magic then
- msg_print("Your anti-magic shell disrupts any magic attempts.")
- elseif (player.inertia_controlled_spell ~= -1) and (player.wild_mode == FALSE) then
- __spell_spell[player.inertia_controlled_spell]()
- end
- end,
-}
-
-stop_inertia_controlled_spell = function()
- player.inertia_controlled_spell = -1
- TIMER_INERTIA_CONTROL.enabled = FALSE
- player.update = bor(player.update, PU_MANA)
- return TRUE
-end
-
-add_hooks
-{
- -- Reduce the mana by four times the cost of the spell
- [HOOK_CALC_MANA] = function(msp)
- if player.inertia_controlled_spell ~= -1 then
- msp = msp - (get_mana(player.inertia_controlled_spell) * 4)
- if msp < 0 then msp = 0 end
- return TRUE, msp
- end
- end,
-
- -- Stop a previous spell at birth
- [HOOK_BIRTH_OBJECTS] = function()
- stop_inertia_controlled_spell()
- end,
-}
-
INERTIA_CONTROL = add_spell
{
["name"] = "Inertia Control",
@@ -246,39 +94,8 @@ INERTIA_CONTROL = add_spell
["mana"] = 300,
["mana_max"] = 700,
["fail"] = 95,
- ["spell"] = function()
- if player.inertia_controlled_spell ~= -1 then
- msg_print("You cancel your inertia flow control.")
- return stop_inertia_controlled_spell()
- end
-
- local s = get_school_spell("control", "is_ok_spell", 0)
- if s == -1 then
- return stop_inertia_controlled_spell()
- end
-
- local inertia = __tmp_spells[s].inertia
-
- if inertia == nil then
- msg_print("This spell inertia flow can not be controlled.")
- return stop_inertia_controlled_spell()
- end
- if inertia[1] > get_level(INERTIA_CONTROL, 10) then
- msg_print("This spell inertia flow("..inertia[1]..") is too strong to be controlled by your current spell.")
- return stop_inertia_controlled_spell()
- end
-
- player.inertia_controlled_spell = s
- TIMER_INERTIA_CONTROL.enabled = TRUE
- TIMER_INERTIA_CONTROL.delay = inertia[2]
- TIMER_INERTIA_CONTROL.countdown = TIMER_INERTIA_CONTROL.delay
- player.update = bor(player.update, PU_MANA)
- msg_print("Inertia flow controlling spell "..spell(s).name..".")
- return TRUE
- end,
- ["info"] = function()
- return "level "..get_level(INERTIA_CONTROL, 10)
- end,
+ ["spell"] = function() return meta_inertia_control() end,
+ ["info"] = function() return meta_inertia_control_info() end,
["desc"] = {
"Changes the energy flow of a spell to be continuously recasted",
"at a given interval. The inertia controlled spell reduces your",
diff --git a/src/birth.c b/src/birth.c
index 274b50bf..aaef998c 100644
--- a/src/birth.c
+++ b/src/birth.c
@@ -1038,6 +1038,9 @@ static void player_wipe(void)
/* No companions killed */
p_ptr->companion_killed = 0;
+
+ /* Inertia control */
+ p_ptr->inertia_controlled_spell = -1;
}
@@ -1241,6 +1244,7 @@ static void player_outfit(void)
}
process_hooks(HOOK_BIRTH_OBJECTS, "()");
+ meta_inertia_control_hook_birth_objects();
{
/* Hack -- Give the player some food */
diff --git a/src/dungeon.c b/src/dungeon.c
index ec2ab0e4..fcca8a21 100644
--- a/src/dungeon.c
+++ b/src/dungeon.c
@@ -1345,7 +1345,14 @@ static void process_world(void)
if (!t_ptr->countdown)
{
t_ptr->countdown = t_ptr->delay;
- call_lua(t_ptr->callback, "()", "");
+ if (t_ptr->callback_c)
+ {
+ t_ptr->callback_c();
+ }
+ if (t_ptr->callback)
+ {
+ call_lua(t_ptr->callback, "()", "");
+ }
}
}
diff --git a/src/externs.h b/src/externs.h
index ac2aef20..e89341a4 100644
--- a/src/externs.h
+++ b/src/externs.h
@@ -1605,6 +1605,28 @@ char *melkor_corpse_explosion_info();
bool_ *melkor_mind_steal();
char *melkor_mind_steal_info();
+extern s32b RECHARGE;
+extern s32b SPELLBINDER;
+extern s32b DISPERSEMAGIC;
+extern s32b TRACKER;
+extern s32b INERTIA_CONTROL;
+extern timer_type *TIMER_INERTIA_CONTROL;
+
+bool_ *meta_recharge();
+char *meta_recharge_info();
+bool_ *meta_spellbinder();
+char *meta_spellbinder_info();
+bool_ *meta_disperse_magic();
+char *meta_disperse_magic_info();
+bool_ *meta_tracker();
+char *meta_tracker_info();
+bool_ *meta_inertia_control();
+char *meta_inertia_control_info();
+
+void meta_inertia_control_timer_callback();
+void meta_inertia_control_calc_mana(int *msp);
+void meta_inertia_control_hook_birth_objects();
+
/* randart.c */
extern int get_activation_power(void);
extern void build_prob(cptr learn);
@@ -1716,6 +1738,7 @@ extern int test_mego_name(cptr name);
extern int test_item_name(cptr name);
extern char msg_box(cptr text, int y, int x);
extern timer_type *new_timer(cptr callback, s32b delay);
+extern timer_type *new_timer_c(void (*callback)(), s32b delay);
extern void del_timer(timer_type *t_ptr);
extern int get_keymap_mode();
@@ -2007,6 +2030,7 @@ extern spell_type *grab_spell_type(s16b num);
extern school_type *grab_school_type(s16b num);
extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus);
extern s32b get_level_device(s32b s, s32b max, s32b min);
+extern int get_mana(s32b s);
extern s32b spell_chance(s32b s);
extern s32b get_level(s32b s, s32b max, s32b min);
extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat);
diff --git a/src/init2.c b/src/init2.c
index 71e7bc2b..38de672a 100644
--- a/src/init2.c
+++ b/src/init2.c
@@ -1974,6 +1974,11 @@ static errr init_misc(void)
for (i = 0; i < MAX_EFFECTS; i++)
effects[i].time = 0;
+ /* Initialize timers */
+ TIMER_INERTIA_CONTROL =
+ new_timer_c(meta_inertia_control_timer_callback,
+ 10);
+
return 0;
}
diff --git a/src/loadsave.c b/src/loadsave.c
index 5116acef..033aa3a0 100644
--- a/src/loadsave.c
+++ b/src/loadsave.c
@@ -575,6 +575,7 @@ static bool_ do_extra(int flag)
do_s32b(&p_ptr->loan, flag);
do_s32b(&p_ptr->loan_time, flag);
do_s16b(&p_ptr->absorb_soul, flag);
+ do_s32b(&p_ptr->inertia_controlled_spell, flag);
do_s16b(&p_ptr->chaos_patron, flag);
@@ -1062,6 +1063,16 @@ static void do_byte(byte *v, int flag)
exit(0);
}
+static void do_bool(bool_ *f, int flag)
+{
+ byte b = *f;
+ do_byte(&b, flag);
+ if (flag == LS_LOAD)
+ {
+ *f = b;
+ }
+}
+
static void do_u16b(u16b *v, int flag)
{
if (flag == LS_LOAD)
@@ -2500,6 +2511,24 @@ void do_fate(int i, int flag)
}
/*
+ * Load/save timers.
+ */
+static void do_timers(int flag)
+{
+ timer_type *t_ptr;
+
+ for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next)
+ {
+ if (t_ptr->callback_c)
+ {
+ do_bool(&t_ptr->enabled, flag);
+ do_s32b(&t_ptr->delay, flag);
+ do_s32b(&t_ptr->countdown, flag);
+ }
+ }
+}
+
+/*
* Actually read the savefile
*/
static bool_ do_savefile_aux(int flag)
@@ -2569,6 +2598,9 @@ static bool_ do_savefile_aux(int flag)
strcpy(loaded_game_module, game_module);
do_string(loaded_game_module, 80, flag);
+ /* Timers */
+ do_timers(flag);
+
/* Read RNG state */
do_randomizer(flag);
if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Randomizer Info");
diff --git a/src/lua_bind.c b/src/lua_bind.c
index a01b1fbc..19fbf529 100644
--- a/src/lua_bind.c
+++ b/src/lua_bind.c
@@ -245,7 +245,7 @@ s32b get_level_device(s32b s, s32b max, s32b min)
return lvl;
}
-static int get_mana(s32b s) {
+int get_mana(s32b s) {
return exec_lua(format("return get_mana(%d)", s));
}
diff --git a/src/player.pkg b/src/player.pkg
index 459ade67..fdde5229 100644
--- a/src/player.pkg
+++ b/src/player.pkg
@@ -1761,22 +1761,6 @@ struct player_type
*/
bool powers[POWER_MAX];
- /** @structvar spellbinder_num
- * @brief Number
- * @note Number of spells bound
- */
- byte spellbinder_num;
- /** @structvar spellbinder[4]
- * @brief Number
- * @note Spell bounds
- */
- u32b spellbinder[4];
- /** @structvar spellbinder_trigger
- * @brief Number
- * @note Spellbinder trigger condition
- */
- byte spellbinder_trigger;
-
/* Corruptions */
bool corrupt_anti_teleport_stopped;
diff --git a/src/spells.pkg b/src/spells.pkg
index 5df1ef10..63e27f73 100644
--- a/src/spells.pkg
+++ b/src/spells.pkg
@@ -490,22 +490,6 @@ extern void teleport_away(int m_idx, int dis);
*/
extern void teleport_player(int dis);
-/** @fn teleport_player_to(int ny, int nx)
- * @brief Teleport player to a grid near coordinate ("ny", "nx").\n
- * @param ny Number \n ny is the y co-ordinate of the location.
- * @brief Y coordinate
- * @param nx Number \n nx is the x co-ordinate of the location.
- * @brief X coordinate
- * @note
- * Teleport player to a grid near the given location\n\n
- * This function is slightly obsessive about correctness.\n
- * This function allows teleporting into vaults (!)\n\n
- * If the location is empty, the player goes there, otherwise they go to
- * a grid as close as possible to the location.
- * @note (see file spells1.c)
- */
-extern void teleport_player_to(int ny, int nx);
-
/** @fn teleport_monster_to(int m_idx, int ny, int nx)
* @brief Teleport monster indicated by "m_idx" to a grid near coordinate
* ("ny", "nx").\n
@@ -2382,22 +2366,6 @@ extern s32b lua_spell_device_chance(s32b chance, int level, int base_level);
*/
extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book);
-/** @name Last Teleportation
- * @brief Coordinates of last successful teleportation
- * @{ */
-/** @var last_teleportation_y
- * @brief Number
- * @note y-coordinate of last successful teleportation
- */
-extern s16b last_teleportation_y;
-
-/** @var last_teleportation_x
- * @brief Number
- * @note x-coordinate of last successful teleportation
- */
-extern s16b last_teleportation_x;
-/** @} */
-
/** @fn get_pos_player(int dis, int *ny=0, int *nx=0)
* @brief Get a grid near the player.\n
* @param dis Number \n is the maximum distance away from the player.
@@ -2647,3 +2615,20 @@ bool_ *melkor_corpse_explosion();
char *melkor_corpse_explosion_info();
bool_ *melkor_mind_steal();
char *melkor_mind_steal_info();
+
+extern s32b RECHARGE;
+extern s32b SPELLBINDER;
+extern s32b DISPERSEMAGIC;
+extern s32b TRACKER;
+extern s32b INERTIA_CONTROL;
+
+bool_ *meta_recharge();
+char *meta_recharge_info();
+bool_ *meta_spellbinder();
+char *meta_spellbinder_info();
+bool_ *meta_disperse_magic();
+char *meta_disperse_magic_info();
+bool_ *meta_tracker();
+char *meta_tracker_info();
+bool_ *meta_inertia_control();
+char *meta_inertia_control_info();
diff --git a/src/spells3.c b/src/spells3.c
index 7fff9935..47abba72 100644
--- a/src/spells3.c
+++ b/src/spells3.c
@@ -73,6 +73,13 @@ s32b MELKOR_CURSE;
s32b MELKOR_CORPSE_EXPLOSION;
s32b MELKOR_MIND_STEAL;
+s32b RECHARGE;
+s32b SPELLBINDER;
+s32b DISPERSEMAGIC;
+s32b TRACKER;
+s32b INERTIA_CONTROL;
+timer_type *TIMER_INERTIA_CONTROL = 0;
+
/* FIXME: Hackish workaround while we're still tied to Lua. This lets
us return Lua's "nil" and a non-nil value (which is all the s_aux.lua
cares about). */
@@ -2149,3 +2156,306 @@ char *melkor_mind_steal_info()
get_level_s(MELKOR_MIND_STEAL, 50));
return buf;
}
+
+bool_ *meta_recharge()
+{
+ recharge(60 + get_level_s(RECHARGE, 140));
+ return CAST;
+}
+
+char *meta_recharge_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "power %d",
+ 60 + get_level_s(RECHARGE, 140));
+ return buf;
+}
+
+static int get_spellbinder_max()
+{
+ int i = get_level_s(SPELLBINDER, 4);
+ if (i > 4)
+ {
+ i = 4;
+ }
+ return i;
+}
+
+bool_ *meta_spellbinder()
+{
+ if (p_ptr->spellbinder_num != 0)
+ {
+ typedef struct trigger trigger;
+ struct trigger {
+ int idx;
+ cptr desc;
+ };
+ trigger triggers[] = {
+ { SPELLBINDER_HP75, "75% HP", },
+ { SPELLBINDER_HP50, "50% HP", },
+ { SPELLBINDER_HP25, "25% HP", },
+ { -1, NULL, },
+ };
+ int trigger_idx = -1;
+ int i;
+
+ assert(p_ptr->spellbinder_trigger >= 0);
+
+ for (trigger_idx = 0; triggers[trigger_idx].idx >= 0; trigger_idx++)
+ {
+ if (triggers[trigger_idx].idx == p_ptr->spellbinder_trigger)
+ {
+ break;
+ }
+ }
+
+ msg_print("The spellbinder is already active.");
+ msg_format("It will trigger at %s.", triggers[trigger_idx].desc);
+ msg_print("With the spells: ");
+ for (i = 0; i < p_ptr->spellbinder_num; i++)
+ {
+ msg_print(school_spells[p_ptr->spellbinder[i]].name);
+ }
+
+ /* Doesn't cost anything */
+ return NO_CAST;
+ }
+ else
+ {
+ char c;
+ int i;
+
+ if (!get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", &c))
+ {
+ return NO_CAST;
+ }
+
+ switch (c)
+ {
+ case 'a':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP75;
+ break;
+ case 'b':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP50;
+ break;
+ case 'c':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP25;
+ break;
+ default:
+ return NO_CAST;
+
+ }
+
+ p_ptr->spellbinder_num = get_spellbinder_max();
+ i = p_ptr->spellbinder_num;
+ while (i > 0)
+ {
+ s32b s = get_school_spell("bind", "is_ok_spell", 0);
+ if (s == -1)
+ {
+ p_ptr->spellbinder_trigger = 0;
+ p_ptr->spellbinder_num = 0;
+ return CAST;
+ } else {
+ if (school_spells[s].skill_level > 7 + get_level_s(SPELLBINDER, 35))
+ {
+ msg_format("You are only allowed spells with a base level of %d.", (7 + get_level_s(SPELLBINDER, 35)));
+ return CAST;
+ }
+ }
+
+ p_ptr->spellbinder[i] = s;
+ i = i - 1;
+ }
+
+ p_ptr->energy = p_ptr->energy - 3100;
+ msg_print("Spellbinder ready.");
+ return CAST;
+ }
+}
+
+char *meta_spellbinder_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "number %d max level %d",
+ get_spellbinder_max(),
+ (7 + get_level_s(SPELLBINDER, 35)));
+ return buf;
+}
+
+bool_ *meta_disperse_magic()
+{
+ set_blind(0);
+ set_lite(0);
+ if (get_level_s(DISPERSEMAGIC, 50) >= 5)
+ {
+ set_confused(0);
+ set_image(0);
+ }
+ if (get_level_s(DISPERSEMAGIC, 50) >= 10)
+ {
+ set_slow(0);
+ set_fast(0, 0);
+ set_light_speed(0);
+ }
+ if (get_level_s(DISPERSEMAGIC, 50) >= 15)
+ {
+ set_stun(0);
+ set_meditation(0);
+ set_cut(0);
+ }
+ if (get_level_s(DISPERSEMAGIC, 50) >= 20)
+ {
+ set_hero(0);
+ set_shero(0);
+ set_blessed(0);
+ set_shield(0, 0, 0, 0, 0);
+ set_afraid(0);
+ set_parasite(0, 0);
+ set_mimic(0, 0, 0);
+ }
+ return CAST;
+}
+
+char *meta_disperse_magic_info()
+{
+ return "";
+}
+
+bool_ *meta_tracker()
+{
+ if ((last_teleportation_y < 0) ||
+ (last_teleportation_x < 0))
+ {
+ msg_print("There has not been any teleporatation here.");
+ }
+ else
+ {
+ teleport_player_to(last_teleportation_y, last_teleportation_x);
+ }
+ return CAST;
+}
+
+char *meta_tracker_info()
+{
+ return "";
+}
+
+static void stop_inertia_controlled_spell()
+{
+ assert(TIMER_INERTIA_CONTROL != NULL);
+
+ p_ptr->inertia_controlled_spell = -1;
+ TIMER_INERTIA_CONTROL->enabled = FALSE;
+ p_ptr->update = p_ptr->update | PU_MANA;
+}
+
+void meta_inertia_control_hook_birth_objects()
+{
+ stop_inertia_controlled_spell();
+}
+
+static bool_ lua_var_is_nil(cptr var)
+{
+ char buf[128];
+ sprintf(buf, "return (%s == nil)", var);
+ return exec_lua(buf);
+}
+
+bool_ *meta_inertia_control()
+{
+ s32b s;
+ char prefix[128];
+ char inertia_0_var[128];
+ char inertia_1_var[128];
+ int inertia_0;
+ int inertia_1;
+
+ if (p_ptr->inertia_controlled_spell != -1)
+ {
+ msg_print("You cancel your inertia flow control.");
+ stop_inertia_controlled_spell();
+ return NO_CAST;
+ }
+
+ s = get_school_spell("control", "is_ok_spell", 0);
+ if (s == -1)
+ {
+ stop_inertia_controlled_spell();
+ return NO_CAST;
+ }
+
+ sprintf(prefix, "__tmp_spells[%d].inertia", (int) s);
+ sprintf(inertia_0_var, "__tmp_spells[%d].inertia[1]", (int) s);
+ sprintf(inertia_1_var, "__tmp_spells[%d].inertia[2]", (int) s);
+
+ if (lua_var_is_nil(prefix))
+ {
+ msg_print("This spell inertia flow can not be controlled.");
+ stop_inertia_controlled_spell();
+ return NO_CAST;
+ }
+
+ inertia_0 = get_lua_int(inertia_0_var);
+ if (inertia_0 > get_level_s(INERTIA_CONTROL, 10))
+ {
+ msg_format("This spell inertia flow(%d) is too strong to be controlled by your current spell.", inertia_0);
+ stop_inertia_controlled_spell();
+ return NO_CAST;
+ }
+
+ inertia_1 = get_lua_int(inertia_1_var);
+
+ p_ptr->inertia_controlled_spell = s;
+ TIMER_INERTIA_CONTROL->enabled = TRUE;
+ TIMER_INERTIA_CONTROL->delay = inertia_1;
+ TIMER_INERTIA_CONTROL->countdown = TIMER_INERTIA_CONTROL->delay;
+ p_ptr->update |= PU_MANA;
+ msg_format("Inertia flow controlling spell %s.", school_spells[s].name);
+ return CAST;
+}
+
+char *meta_inertia_control_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level %d",
+ get_level_s(INERTIA_CONTROL, 10));
+ return buf;
+}
+
+void meta_inertia_control_timer_callback()
+{
+ /* Don't cast a controlled spell in wilderness mode */
+ if (p_ptr->antimagic)
+ {
+ msg_print("Your anti-magic field disrupts any magic attempts.");
+ }
+ else if (p_ptr->anti_magic)
+ {
+ msg_print("Your anti-magic shell disrupts any magic attempts.");
+ }
+ else if ((p_ptr->inertia_controlled_spell != -1) &&
+ (!p_ptr->wild_mode))
+ {
+ char buf[128];
+ sprintf(buf,
+ "__spell_spell[%d]()",
+ p_ptr->inertia_controlled_spell);
+ exec_lua(buf);
+ }
+}
+
+void meta_inertia_control_calc_mana(int *msp)
+{
+ if (p_ptr->inertia_controlled_spell != -1)
+ {
+ *msp = *msp - (get_mana(p_ptr->inertia_controlled_spell) * 4);
+ if (*msp < 0)
+ {
+ *msp = 0;
+ }
+ }
+}
diff --git a/src/types.h b/src/types.h
index ea66ff5f..8e06c4fd 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1843,6 +1843,9 @@ struct player_type
/* Help */
help_info help;
+ /* Inertia control */
+ s32b inertia_controlled_spell;
+
/*** Temporary fields ***/
bool_ did_nothing; /* True if the last action wasnt a real action */
@@ -2487,7 +2490,8 @@ struct timer_type
s32b delay; /* Delay between activations */
s32b countdown; /* The current number of turns passed, when it reaches delay it fires */
- cptr callback; /* The lua function to call upon firing(no C callback yet .. maybe) */
+ cptr callback; /* The lua function to call upon firing (if any) */
+ void (*callback_c)(); /* The C function to call upon firing */
};
/*
diff --git a/src/util.c b/src/util.c
index f1b0710e..a195cfc9 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4417,7 +4417,7 @@ void scansubdir(cptr dir)
/*
* Timers
*/
-timer_type *new_timer(cptr callback, s32b delay)
+static timer_type *new_timer_init(s32b delay)
{
timer_type *t_ptr;
@@ -4425,7 +4425,8 @@ timer_type *new_timer(cptr callback, s32b delay)
t_ptr->next = gl_timers;
gl_timers = t_ptr;
- t_ptr->callback = string_make(callback);
+ t_ptr->callback_c = NULL;
+ t_ptr->callback = NULL;
t_ptr->delay = delay;
t_ptr->countdown = delay;
t_ptr->enabled = FALSE;
@@ -4433,6 +4434,20 @@ timer_type *new_timer(cptr callback, s32b delay)
return t_ptr;
}
+timer_type *new_timer(cptr callback, s32b delay)
+{
+ timer_type *t_ptr = new_timer_init(delay);
+ t_ptr->callback = string_make(callback);
+ return t_ptr;
+}
+
+timer_type *new_timer_c(void (*callback)(), s32b delay)
+{
+ timer_type *t_ptr = new_timer_init(delay);
+ t_ptr->callback_c = callback;
+ return t_ptr;
+}
+
void del_timer(timer_type *t_ptr)
{
timer_type *i, *old;
diff --git a/src/xtra1.c b/src/xtra1.c
index a2f64d0e..c20b9036 100644
--- a/src/xtra1.c
+++ b/src/xtra1.c
@@ -1793,6 +1793,8 @@ static void calc_mana(void)
msp = process_hooks_return[0].num;
}
+ meta_inertia_control_calc_mana(&msp);
+
/* Mana can never be negative */
if (msp < 0) msp = 0;