diff options
author | Bardur Arantsson <bardur@scientician.net> | 2012-05-08 18:59:59 +0200 |
---|---|---|
committer | Bardur Arantsson <bardur@scientician.net> | 2012-05-08 20:15:58 +0200 |
commit | 6ef98743b002c48fb3bf720fb07936e34926b313 (patch) | |
tree | b834dbbc9501533a29e612d9594c72e749105766 /src | |
parent | 4275c9d3e7a44080997fce9974d442ba4f9f4a54 (diff) |
Lua: Move "Meta" spell functions to C
Diffstat (limited to 'src')
-rw-r--r-- | src/birth.c | 4 | ||||
-rw-r--r-- | src/dungeon.c | 9 | ||||
-rw-r--r-- | src/externs.h | 24 | ||||
-rw-r--r-- | src/init2.c | 5 | ||||
-rw-r--r-- | src/loadsave.c | 32 | ||||
-rw-r--r-- | src/lua_bind.c | 2 | ||||
-rw-r--r-- | src/player.pkg | 16 | ||||
-rw-r--r-- | src/spells.pkg | 49 | ||||
-rw-r--r-- | src/spells3.c | 310 | ||||
-rw-r--r-- | src/types.h | 6 | ||||
-rw-r--r-- | src/util.c | 19 | ||||
-rw-r--r-- | src/xtra1.c | 2 |
12 files changed, 425 insertions, 53 deletions
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 */ }; /* @@ -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; |