diff --git a/act.h b/act.h index 6814807b..48e916f7 100755 --- a/act.h +++ b/act.h @@ -615,6 +615,8 @@ ACMDCHECK(can_vampiric_shape_change); ACMD_DECL(do_vampiric_shape_change); ACMDCHECK(can_vampiric_dominate); ACMD_DECL(do_vampiric_dominate); +ACMD_DECL(do_quick_chant); + /***************************************************************************** * Begin Functions and defines for act.other.c ****************************************************************************/ diff --git a/act.offensive.c b/act.offensive.c index 9ce45798..82c949dc 100755 --- a/act.offensive.c +++ b/act.offensive.c @@ -9135,6 +9135,60 @@ ACMD(do_blood_drain) } +ACMD(do_quick_chant) +{ + + int uses_remaining = 0; + + if (subcmd == SCMD_QUICK_CHANT && !HAS_FEAT(ch, FEAT_QUICK_CHANT)) + { + send_to_char(ch, "You do not have the quick chant feat.\r\n"); + return; + } + else if (subcmd == SCMD_QUICK_MIND && !HAS_FEAT(ch, FEAT_QUICK_MIND)) + { + send_to_char(ch, "You do not have the quick mind feat.\r\n"); + return; + } + + if ((uses_remaining = daily_uses_remaining(ch, (subcmd == SCMD_QUICK_CHANT) ? FEAT_QUICK_CHANT : FEAT_QUICK_MIND)) == 0) + { + send_to_char(ch, "You must recover the energy required to use this ability again.\r\n"); + return; + } + + if (uses_remaining < 0) + { + send_to_char(ch, "You are not experienced enough.\r\n"); + return; + } + + if (subcmd == SCMD_QUICK_CHANT) + { + if (ch->char_specials.quick_chant) + { + send_to_char(ch, "You are already benefitting from quick chant.\r\n"); + return; + } + send_to_char(ch, "Youn invoke your quick chant ability. The next non-ritual spell you cast will only use a swift action.\r\n"); + ch->char_specials.quick_chant = true; + } + else + { + if (ch->char_specials.quick_mind) + { + send_to_char(ch, "You are already benefitting from quick mind.\r\n"); + return; + } + send_to_char(ch, "Youn invoke your quick mind ability. The next non-ritual power your manifest will only use a swift action.\r\n"); + ch->char_specials.quick_mind = true; + } + + if (!IS_NPC(ch)) + start_daily_use_cooldown(ch, (subcmd == SCMD_QUICK_CHANT) ? FEAT_QUICK_CHANT : FEAT_QUICK_MIND); + +} + /* cleanup! */ #undef RAGE_AFFECTS #undef D_STANCE_AFFECTS diff --git a/feats.c b/feats.c index fa24187d..5442f03b 100644 --- a/feats.c +++ b/feats.c @@ -2744,9 +2744,17 @@ void assign_feats(void) "Each rank in this feat will give your familiar: 1 AC, 10 Hit-points, +1 to " "strength, dexterity and constitution."); +#ifdef CAMPAIGN_FR feato(FEAT_QUICK_CHANT, "quick chant", TRUE, TRUE, FALSE, FEAT_TYPE_SPELLCASTING, - "you can cast spells faster", - "You can cast spells about 50 percent faster than normal with this feat."); + "You can cast spells faster.", + "You can cast/manifest ritual spells/psionic powers about 50 percent faster than normal with this feat. You also have a 10% chance to cast/manifest " + "any spell/psionic power as if it were quickened, using a swift action to cast/manifest instead of a standard action.\r\n"); +#else + feato(FEAT_QUICK_CHANT, "quick chant", TRUE, TRUE, FALSE, FEAT_TYPE_SPELLCASTING, + "You can cast spells faster.", + "You can cast/manifest ritual spells/psionic powers about 50 percent faster than normal with this feat."); +#endif + feato(FEAT_AUGMENT_SUMMONING, "augment summoning", TRUE, TRUE, FALSE, FEAT_TYPE_SPELLCASTING, "enhance summoned creatures", diff --git a/interpreter.c b/interpreter.c index a0333b94..e39cfcb6 100755 --- a/interpreter.c +++ b/interpreter.c @@ -605,6 +605,8 @@ cpp_extern const struct command_info cmd_info[] = { {"qecho", "qec", POS_DEAD, do_qcomm, LVL_STAFF, SCMD_QECHO, TRUE, ACTION_NONE, {0, 0}, NULL}, {"quest", "que", POS_DEAD, do_quest, 0, 0, FALSE, ACTION_NONE, {0, 0}, NULL}, {"qui", "qui", POS_DEAD, do_quit, 0, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"quickchant", "quickc", POS_FIGHTING, do_quick_chant, 0, SCMD_QUICK_CHANT, TRUE, ACTION_NONE, {0, 0}, NULL}, + {"quickmind", "quickm", POS_FIGHTING, do_quick_chant, 0, SCMD_QUICK_MIND, TRUE, ACTION_NONE, {0, 0}, NULL}, {"quit", "quit", POS_DEAD, do_quit, 0, SCMD_QUIT, TRUE, ACTION_NONE, {0, 0}, NULL}, {"qsay", "qsay", POS_RECLINING, do_qcomm, 0, SCMD_QSAY, TRUE, ACTION_NONE, {0, 0}, NULL}, {"qref", "qref", POS_DEAD, do_qref, LVL_BUILDER, 0, TRUE, ACTION_NONE, {0, 0}, NULL}, diff --git a/interpreter.h b/interpreter.h index bf7c3ea7..ec68fdbc 100755 --- a/interpreter.h +++ b/interpreter.h @@ -149,6 +149,9 @@ struct alias_data #define SCMD_PILFER 1 +#define SCMD_QUICK_CHANT 1 +#define SCMD_QUICK_MIND 2 + /* Necessary for CMD_IS macro. Borland needs the structure defined first * so it has been moved down here. */ /* Global buffering system */ diff --git a/limits.c b/limits.c index 7e94eb8e..cb92816d 100755 --- a/limits.c +++ b/limits.c @@ -2162,8 +2162,7 @@ void self_buffing(void) while (GET_BUFF(ch, GET_CURRENT_BUFF_SLOT(ch), 0) == 0 && GET_CURRENT_BUFF_SLOT(ch) < (MAX_BUFFS + 1)) { - GET_CURRENT_BUFF_SLOT(ch) - ++; + GET_CURRENT_BUFF_SLOT(ch)++; } if (GET_CURRENT_BUFF_SLOT(ch) >= MAX_BUFFS) { @@ -2185,7 +2184,16 @@ void self_buffing(void) if (IS_AFFECTED(ch, AFF_TIME_STOPPED)) GET_BUFF_TIMER(ch) = 1; else + { +#ifdef CAMPAIGN_FR + if (spell_info[spellnum].ritual_spell) + GET_BUFF_TIMER(ch) = MAX(6, spell_info[spellnum].time + 1); + else + GET_BUFF_TIMER(ch) = 6; +#else GET_BUFF_TIMER(ch) = spell_info[spellnum].time + 1; +#endif + } if (is_spell) { diff --git a/missions.c b/missions.c index 577f497c..19a88e16 100644 --- a/missions.c +++ b/missions.c @@ -170,7 +170,7 @@ SPECIAL(faction_mission) if (GET_MISSION_COOLDOWN(ch) > 0 && GET_LEVEL(ch) < LVL_GRSTAFF) { - send_to_char(ch, "You are not ready to take a mission right now. Check the cooldowns command for more info.\r\n"); + send_to_char(ch, "take a mission right now. Check the cooldowns command for more info.\r\n"); return 1; } diff --git a/spell_parser.c b/spell_parser.c index e850ca1b..55c41d03 100755 --- a/spell_parser.c +++ b/spell_parser.c @@ -1440,12 +1440,10 @@ EVENTFUNC(event_casting) } } if (affected_by_spell(ch, PSIONIC_ABILITY_PSIONIC_FOCUS)) - CASTING_TIME(ch) - --; + CASTING_TIME(ch)--; } - CASTING_TIME(ch) - --; + CASTING_TIME(ch)--; // chance quick chant bumped us to finish early if (CASTING_TIME(ch) <= 0) @@ -1494,6 +1492,7 @@ int cast_spell(struct char_data *ch, struct char_data *tch, int position = GET_POS(ch); int ch_class = CLASS_WIZARD, clevel = 0; int casting_time = 0; + bool quickened = FALSE; if (spellnum < 0 || spellnum > TOP_SPELL_DEFINE) { @@ -1654,8 +1653,88 @@ int cast_spell(struct char_data *ch, struct char_data *tch, break; } +#ifdef CAMPAIGN_FR + // We don't use casting times unless it's a ritual spell + if (SINFO.ritual_spell) + casting_time = SINFO.time; + else + casting_time = 1; +#else /* establish base casting time for spell */ casting_time = SINFO.time; +#endif + + /* meta magic! */ + if (!IS_NPC(ch)) + { + if (IS_SET(metamagic, METAMAGIC_QUICKEN)) + { + casting_time = 0; + quickened = TRUE; + } + if ((ch_class == CLASS_SORCERER || ch_class == CLASS_BARD) && + IS_SET(metamagic, METAMAGIC_MAXIMIZE) && + !IS_SET(metamagic, METAMAGIC_QUICKEN)) + { + // Sorcerers with Arcane Bloodline + if (IS_SET(metamagic, METAMAGIC_ARCANE_ADEPT) || HAS_FEAT(ch, FEAT_ARCANE_APOTHEOSIS)) + ; + else + casting_time = casting_time * 3 / 2; + } + } + + if (!IS_NPC(ch) && HAS_ELDRITCH_SPELL_CRIT(ch)) + { + HAS_ELDRITCH_SPELL_CRIT(ch) = false; + casting_time = 0; + quickened = TRUE; + } + + if (spellnum == PSIONIC_MIND_TRAP) + { + casting_time = 0; + quickened = TRUE; + } + +#ifndef CAMPAIGN_FR + if (spellnum >= PSIONIC_POWER_START && spellnum <= PSIONIC_POWER_END) + { + casting_time += get_augment_casting_time_adjustment(ch); + if (IS_BUFFING(ch)) + GET_BUFF_TIMER(ch) += get_augment_casting_time_adjustment(ch); + } +#endif + + if (spellnum == PSIONIC_ENERGY_ADAPTATION_SPECIFIED || spellnum == PSIONIC_ENERGY_ADAPTATION) + { + if (GET_AUGMENT_PSP(ch) >= 4) + { + casting_time = 1; + quickened = TRUE; + } + } + +#ifdef CAMPAIGN_FR + if (quickened) + { + if (!is_action_available(ch, atSWIFT, FALSE)) + { + send_to_char(ch, "This action requires a swift action to be available.\r\n"); + return 0; + } + USE_SWIFT_ACTION(ch); + } + else + { + if (!is_action_available(ch, atSTANDARD, FALSE)) + { + send_to_char(ch, "This action requires a standard action to be available.\r\n"); + return 0; + } + USE_STANDARD_ACTION(ch); + } +#endif /* Going to adjust spell queue and establish what class the character will be using for casting this spell */ @@ -1733,57 +1812,22 @@ will be using for casting this spell */ return 0; } - /* meta magic! */ - if (!IS_NPC(ch)) - { - if (IS_SET(metamagic, METAMAGIC_QUICKEN)) - { - casting_time = 0; - } - if ((ch_class == CLASS_SORCERER || ch_class == CLASS_BARD) && - IS_SET(metamagic, METAMAGIC_MAXIMIZE) && - !IS_SET(metamagic, METAMAGIC_QUICKEN)) - { - // Sorcerers with Arcane Bloodline - if (IS_SET(metamagic, METAMAGIC_ARCANE_ADEPT) || HAS_FEAT(ch, FEAT_ARCANE_APOTHEOSIS)) - ; - else - casting_time = casting_time * 3 / 2; - } - } - - if (!IS_NPC(ch) && HAS_ELDRITCH_SPELL_CRIT(ch)) - { - HAS_ELDRITCH_SPELL_CRIT(ch) = false; - casting_time = 0; - } - - if (spellnum == PSIONIC_MIND_TRAP) - { - casting_time = 0; - } - - if (spellnum >= PSIONIC_POWER_START && spellnum <= PSIONIC_POWER_END) - { - casting_time += get_augment_casting_time_adjustment(ch); - if (IS_BUFFING(ch)) - GET_BUFF_TIMER(ch) += get_augment_casting_time_adjustment(ch); - } - - if (spellnum == PSIONIC_ENERGY_ADAPTATION_SPECIFIED || spellnum == PSIONIC_ENERGY_ADAPTATION) - { - if (GET_AUGMENT_PSP(ch) >= 4) - casting_time = 0; - } - /* handle spells with no casting time */ if (casting_time <= 0 && !IS_NPC(ch)) { /* we disabled this for npc's */ send_to_char(ch, "%s", CONFIG_OK); say_spell(ch, spellnum, tch, tobj, FALSE); - /* prevents spell spamming */ +#ifdef CAMPAIGN_FR + CASTING_TIME(ch) = casting_time; + CASTING_TCH(ch) = tch; + CASTING_TOBJ(ch) = tobj; + CASTING_SPELLNUM(ch) = spellnum; + CASTING_METAMAGIC(ch) = metamagic; +#else + /* mandatory wait-state for any spell */ USE_MOVE_ACTION(ch); +#endif return (call_magic(ch, tch, tobj, spellnum, metamagic, CASTER_LEVEL(ch), CAST_SPELL)); } @@ -1830,8 +1874,11 @@ will be using for casting this spell */ NEW_EVENT(eCASTING, ch, NULL, 1 * PASSES_PER_SEC); } +#ifndef CAMPAIGN_FR /* mandatory wait-state for any spell */ USE_MOVE_ACTION(ch); +#endif + } // this return value has to be checked -zusuk return (1); @@ -2687,6 +2734,7 @@ void unused_spell(int spl) spell_info[spl].memtime = 0; spell_info[spl].schoolOfMagic = NOSCHOOL; // noschool spell_info[spl].quest = FALSE; + spell_info[spl].ritual_spell = FALSE; } void unused_skill(int spl) diff --git a/spells.h b/spells.h index 6db6f7e8..7bd68c7d 100755 --- a/spells.h +++ b/spells.h @@ -1313,6 +1313,7 @@ struct spell_info_type int duration; /* assigned in the code currently */ int saving_throw; /* assigned in the code currently */ int resistance; /* spell resistance, assigned in code currently */ + bool ritual_spell; // If this is a ritual spell, it will have a cast time, otherwise it won't }; /* wall struct for wall spells, like wall of fire, force, thorns, etc */ diff --git a/structs.h b/structs.h index 2468c789..6aba28c6 100755 --- a/structs.h +++ b/structs.h @@ -4104,6 +4104,9 @@ struct char_special_data bool drainKilled; // true if killed by an energy draining creature (like a vampire), while under the effect of AFFECT_LEVEL_DRAIN bool banishing_blade_procced_this_round; // has the creature had a banishing blade affect attempted against him this round? + + bool quick_chant; // true if under the effect of quick chant + bool quick_mind; // true if under the effect of quick mind }; /* old memorization struct */ diff --git a/utils.c b/utils.c index 124aa7bf..910fc605 100755 --- a/utils.c +++ b/utils.c @@ -4381,6 +4381,10 @@ int get_daily_uses(struct char_data *ch, int featnum) int daily_uses = 0; switch (featnum) { + case FEAT_QUICK_CHANT: + case FEAT_QUICK_MIND: + daily_uses = 2; + break; case FEAT_VAMPIRE_CHILDREN_OF_THE_NIGHT: daily_uses = 1; break;