From 6ef98743b002c48fb3bf720fb07936e34926b313 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 8 May 2012 18:59:59 +0200 Subject: Lua: Move "Meta" spell functions to C --- lib/core/util.lua | 7 - lib/mods/theme/core/util.lua | 7 - lib/mods/theme/scpt/s_meta.lua | 203 ++------------------------- lib/scpt/s_meta.lua | 203 ++------------------------- src/birth.c | 4 + src/dungeon.c | 9 +- src/externs.h | 24 ++++ src/init2.c | 5 + src/loadsave.c | 32 +++++ src/lua_bind.c | 2 +- src/player.pkg | 16 --- src/spells.pkg | 49 +++---- src/spells3.c | 310 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 6 +- src/util.c | 19 ++- src/xtra1.c | 2 + 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) @@ -2499,6 +2510,24 @@ void do_fate(int i, int flag) do_byte((byte*)&fates[i].know, 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 */ @@ -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; -- cgit v1.2.3