Skip to content

Commit

Permalink
Added downgrade command to downgrade high level items to lower level …
Browse files Browse the repository at this point in the history
…usage, including reduction of stats in the process.

Fixed auto prep to cycle through different spellcasting classes when you rest, auto-prepping them all.
Identifying an item now flags it identified and can henchforth be identified by anyone regardless of Arcana skill.
Added a saveeverything command on the rare occasion we need to save all zones.
Began the background system a la 'D&D 5e' system.
Changed various skill names, combined some skills, and added some new skills.
Monk weapons now do monk barehand damage if barehand damage dice are higher than the weapon dice.
Added a temple spec proc that offers healing for gold.
All warlock blast essences have lower durations, cooldowns on how often they can be applied to a single target, and can be stacked with each other.
Fixed duration on see the unseen warlock spell.
Eldritch shape and essence now save over sessions.
  • Loading branch information
GickerLDS committed Sep 11, 2024
1 parent d1ace3b commit bfc69f7
Show file tree
Hide file tree
Showing 27 changed files with 1,050 additions and 135 deletions.
2 changes: 2 additions & 0 deletions act.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ ACMD_DECL(do_bags);
#define SCMD_SORTFROM 2

ACMD_DECL(do_activate);
ACMD_DECL(do_downgrade);

/* AUCTIONING STATES */
#define AUC_NULL_STATE 0 /* not doing anything */
Expand Down Expand Up @@ -996,6 +997,7 @@ ACMD_DECL(do_holyweapon);
ACMD_DECL(do_award);
ACMD_DECL(do_show_blockers);
ACMD_DECL(do_save_objects_to_database);
ACMD_DECL(do_save_everything);

ACMD_DECL(do_touch_spells);
ACMD_DECL(do_weapon_touch);
Expand Down
208 changes: 202 additions & 6 deletions act.item.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "hunts.h"
#include "class.h"
#include "spell_prep.h"
#include "genobj.h"

/* local function prototypes */
/* do_get utility functions */
Expand All @@ -67,6 +68,8 @@ int hands_used(struct char_data *ch);
int hands_available(struct char_data *ch);
static void wear_message(struct char_data *ch, struct obj_data *obj, int where);

int can_lore_target(struct char_data *ch, struct char_data *target_ch, struct obj_data *target_obj, bool silent);

/**** start file code *****/

/*
Expand Down Expand Up @@ -4147,7 +4150,8 @@ ACMD(do_wear)
if (CAN_SEE_OBJ(ch, obj) && (where = find_eq_pos(ch, obj, 0)) >= 0)
{
if (level_allowed < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use %s.\r\n", GET_OBJ_SHORT(obj));
send_to_char(ch, "You are not experienced enough to use %s.\r\n"
"You can downgrade the item to a lower level. See HELP DOWNGRADE\r\n", GET_OBJ_SHORT(obj));
else if (GET_OBJ_TYPE(obj) == ITEM_CLANARMOR && (GET_CLAN(ch) == NO_CLAN || (GET_OBJ_VAL(obj, 2) + 1) != GET_CLAN(ch)))
send_to_char(ch, "You are in clan %d, This belongs to clan %d.\r\n", GET_CLAN(ch), GET_OBJ_VAL(obj, 2));
else
Expand All @@ -4172,7 +4176,8 @@ ACMD(do_wear)
if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
send_to_char(ch, "You don't seem to have any %ss.\r\n", arg1);
else if (level_allowed < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use %s.\r\n", GET_OBJ_SHORT(obj));
send_to_char(ch, "You are not experienced enough to use %s.\r\n"
"You can downgrade the item to a lower level. See HELP DOWNGRADE\r\n", GET_OBJ_SHORT(obj));
else if (GET_OBJ_TYPE(obj) == ITEM_CLANARMOR &&
(GET_CLAN(ch) == NO_CLAN || (GET_OBJ_VAL(obj, 2) + 1) != GET_CLAN(ch)))
send_to_char(ch, "You are in clan %d, That belongs to clan %d.\r\n", GET_CLAN(ch), GET_OBJ_VAL(obj, 2));
Expand All @@ -4195,7 +4200,8 @@ ACMD(do_wear)
if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying)))
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1);
else if (level_allowed < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use %s.\r\n", GET_OBJ_SHORT(obj));
send_to_char(ch, "You are not experienced enough to use %s.\r\n"
"You can downgrade the item to a lower level. See HELP DOWNGRADE\r\n", GET_OBJ_SHORT(obj));
else if (GET_OBJ_TYPE(obj) == ITEM_CLANARMOR &&
(GET_CLAN(ch) == NO_CLAN || (GET_OBJ_VAL(obj, 2) + 1) != GET_CLAN(ch)))
send_to_char(ch, "You are in clan %d, That belongs to clan %d.\r\n", GET_CLAN(ch), GET_OBJ_VAL(obj, 2));
Expand Down Expand Up @@ -4236,7 +4242,8 @@ bool perform_wield(struct char_data *ch, struct obj_data *obj, bool not_silent)
else if (level_allowed < GET_OBJ_LEVEL(obj))
{
if (not_silent)
send_to_char(ch, "You are not experienced enough to use that.\r\n");
send_to_char(ch, "You are not experienced enough to use that.\r\n"
"You can downgrade the item to a lower level. See HELP DOWNGRADE\r\n");
}
else if (GET_OBJ_TYPE(obj) == ITEM_CLANARMOR &&
(GET_CLAN(ch) == NO_CLAN || GET_OBJ_VAL(obj, 2) != GET_CLAN(ch)))
Expand Down Expand Up @@ -4348,7 +4355,8 @@ ACMD(do_grab)
else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg);
else if (level_allowed < GET_OBJ_LEVEL(obj))
send_to_char(ch, "You are not experienced enough to use that.\r\n");
send_to_char(ch, "You are not experienced enough to use that.\r\n"
"You can downgrade the item to a lower level. See HELP DOWNGRADE\r\n");
else if (GET_OBJ_TYPE(obj) == ITEM_CLANARMOR &&
(GET_CLAN(ch) == NO_CLAN || GET_OBJ_VAL(obj, 2) != GET_CLAN(ch)))
send_to_char(ch, "You are not in the right clan to use that.\r\n");
Expand Down Expand Up @@ -6776,7 +6784,7 @@ bool setup_outfit_item(struct char_data *ch, struct obj_data *obj)
GET_OBJ_WEIGHT(obj) = GET_OBJ_TYPE(GET_OUTFIT_OBJ(ch)) == ITEM_WEAPON ? weapon_list[GET_OUTFIT_TYPE(ch)].weight : armor_list[GET_OUTFIT_TYPE(ch)].weight;
GET_OBJ_VAL(obj, 4) = GET_OBJ_VAL(GET_OUTFIT_OBJ(ch), OUTFIT_VAL_BONUS);
GET_OBJ_LEVEL(obj) = MAX(0, MIN(30, (GET_OBJ_VAL(obj, 4) * 5) - 5));
GET_OBJ_MATERIAL(obj) = GET_OBJ_VAL(GET_OUTFIT_OBJ(ch), OUTFIT_VAL_MATERIAL);
// GET_OBJ_MATERIAL(obj) = GET_OBJ_VAL(GET_OUTFIT_OBJ(ch), OUTFIT_VAL_MATERIAL);

// we are only adding apply bonuses to weapons, shields or body armor
if (!CAN_WEAR(obj, ITEM_WEAR_HEAD) && !CAN_WEAR(obj, ITEM_WEAR_ARMS) && !CAN_WEAR(obj, ITEM_WEAR_LEGS))
Expand Down Expand Up @@ -7752,4 +7760,192 @@ int find_activate_object_by_spellnum(struct char_data *ch, int spellnum, bool re
return -1;
}

void downgrade_item(struct char_data *ch, struct obj_data *obj, int level)
{

int i = 0, reduce = 0;

if (!obj)
return;

if (!ch)
return;

if (level >= GET_OBJ_LEVEL(obj))
{
send_to_char(ch, "You must select a level below the level of the item you're downgrading.\r\n");
return;
}

// downgraded items lose any special abilities
obj->special_abilities = NULL;

// downgrade items lose any weapon spells
HAS_SPELLS(obj) = 0;
for (i = 0; i < MAX_WEAPON_SPELLS; i++)
{
obj->wpn_spells[i].level = 0;
obj->wpn_spells[i].percent = 0;
obj->wpn_spells[i].inCombat = 0;
obj->wpn_spells[i].spellnum = 0;
}

// downgraded items lose all perm affects
obj->obj_flags.bitvector[0] = obj->obj_flags.bitvector[1] = obj->obj_flags.bitvector[2] = obj->obj_flags.bitvector[3] = 0;

// downgraded items lose any spell activations
obj->activate_spell[0] = obj->activate_spell[1] = obj->activate_spell[2] = obj->activate_spell[3] = obj->activate_spell[4] = 0;

reduce = GET_OBJ_LEVEL(obj) - level;

switch (GET_OBJ_TYPE(obj))
{
case ITEM_ARMOR:
case ITEM_WEAPON:
case ITEM_FIREWEAPON:
case ITEM_MISSILE:
GET_OBJ_VAL(obj, 4) -= reduce / 5;
GET_OBJ_VAL(obj, 4) = MAX(0, GET_OBJ_VAL(obj, 4));
break;
}

for (i = 0; i < MAX_OBJ_AFFECT; i++)
{
if (obj->affected[i].modifier > 0)
{
switch (obj->affected[i].location)
{
case APPLY_HIT: obj->affected[i].modifier -= reduce; break;
case APPLY_MOVE: obj->affected[i].modifier -= reduce * 5; break;
default: obj->affected[i].modifier -= reduce / 5; break;
}
if (obj->affected[i].modifier <= 0)
{
obj->affected[i].modifier = obj->affected[i].bonus_type = obj->affected[i].location = obj->affected[i].specific = 0;
}
}
}

GET_OBJ_LEVEL(obj) = level;

}

ACMD(do_downgrade)
{
char arg[200];
char arg2[200];
char arg3[200];
int cost = 0;

three_arguments(argument, arg, sizeof(arg), arg2, sizeof(arg2), arg3, sizeof(arg3));

if (!*arg)
{
send_to_char(ch, "What item do you wish to downgrade?\r\n");
return;
}

if (!*arg2)
{
send_to_char(ch, "What level do you wish to downgrade the item to?\r\n");
return;
}

int level = atoi(arg2);

if (level < 1)
{
send_to_char(ch, "You cannot downgrade something lower than level 1.\r\n");
return;
}

if (level > 30)
{
send_to_char(ch, "You cannot downgrade something higher than 30.\r\n");
return;
}

struct obj_data *obj = NULL;

if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying)))
{
send_to_char(ch, "You do not seem to have an item by that description in your inventory.\r\n");
return;
}

if (OBJ_FLAGGED(obj, ITEM_DOWNGRADED))
{
send_to_char(ch, "This item has already been downgraded, and cannot be done so again.\r\n");
return;
}

if (level > GET_LEVEL(ch))
{
send_to_char(ch, "You cannot downgrade a level higher than your own.\r\n");
return;
}

if (!can_lore_target(ch, NULL, obj, TRUE))
{
send_to_char(ch, "The object must be identified by a lore check or the identify spell before it can be downgraded.\r\n");
return;
}

cost = GET_OBJ_LEVEL(obj) * 50;

if (GET_GOLD(ch) < cost)
{
send_to_char(ch, "It will cost you %d coins to downgrade this item.\r\n", cost);
return;
}

if (ch->player_specials->downgrade_confirm == NULL)
{
struct obj_data *temp_obj;
if ((temp_obj = read_object(ITEM_PROTOTYPE, VIRTUAL)) == NULL)
{
send_to_char(ch, "There was an error. Please report to a staff member with error code DOWNGRADE001.\r\n");
return;
}
send_to_char(ch, "\tCYour downgraded item will have the following stats:\tn\r\n");
copy_object(temp_obj, obj);
downgrade_item(ch, temp_obj, level);
do_stat_object(ch, temp_obj, ITEM_STAT_MODE_LORE_SKILL);
send_to_char(ch, "\r\n");
send_to_char(ch, "\tCPLEASE NOTE:\tn");
send_to_char(ch, "\tcDowngrading an item will cause it to lose all special ability, perm affects, weapon spells and activated spells.\r\n");
send_to_char(ch, "In addition, it could also lose some or all of its bonuses. This process is irreversable.");
send_to_char(ch, "It will cost you %d coins to downgrade this item.\r\n", cost);
ch->player_specials->downgrade_confirm = randstring(6);
send_to_char(ch, "To proceed with this downgrade type: downgrade %s %d %s\r\n", arg, level, ch->player_specials->downgrade_confirm);
send_to_char(ch, "To abort the downgrade, type: downgrade %s %d cancel\tn\r\n", arg, level);
return;
}
else if (!*arg3)
{
send_to_char(ch, "To proceed with this downgrade type: downgrade %s %d %s\r\n", arg, level, ch->player_specials->downgrade_confirm);
send_to_char(ch, "To abort the downgrade, type: downgrade %s %d cancel\r\n", arg, level);
return;
}
else if (is_abbrev(arg3, "cancel"))
{
send_to_char(ch, "You've aborted the downgrade.\r\n");
ch->player_specials->downgrade_confirm = NULL;
return;
}
else if (strcmp(arg3, ch->player_specials->downgrade_confirm))
{
send_to_char(ch, "To proceed with this downgrade type: downgrade %s %d %s\r\n", arg, level, ch->player_specials->downgrade_confirm);
send_to_char(ch, "To abort the downgrade, type: downgrade %s %d cancel\r\n", arg, level);
}

GET_GOLD(ch) -= cost;
downgrade_item(ch, obj, level);
SET_BIT_AR(GET_OBJ_EXTRA(obj), ITEM_DOWNGRADED);
do_stat_object(ch, obj, ITEM_STAT_MODE_LORE_SKILL);
send_to_char(ch, "\tMYou downgrade %s to level %d.\tn\r\n", obj->short_description, level);
send_to_char(ch, "It cost you %d coins to downgrade this item.\tn\r\n", cost);
ch->player_specials->downgrade_confirm = NULL;
}

/* EOF */
22 changes: 11 additions & 11 deletions act.movement.c
Original file line number Diff line number Diff line change
Expand Up @@ -3252,17 +3252,17 @@ ACMD(do_rest)
break;
}

if (PRF_FLAGGED(ch, PRF_AUTO_PREP))
{
if (count_spellcasting_classes(ch) == 1)
{
do_gen_preparation(ch, "autoprep", 0, class_to_spell_prep_scmd(get_spellcasting_class(ch)));
}
else if (count_spellcasting_classes(ch) > 1)
{
send_to_char(ch, "Since you have multiple classes that can cast spells, you must prepare those spells manually. See 'class info (class name)' to see spell prep commands for your classes.\r\n");
}
}
// if (PRF_FLAGGED(ch, PRF_AUTO_PREP))
// {
// if (count_spellcasting_classes(ch) == 1)
// {
// do_gen_preparation(ch, "autoprep", 0, class_to_spell_prep_scmd(get_spellcasting_class(ch)));
// }
// else if (count_spellcasting_classes(ch) > 1)
// {
// send_to_char(ch, "Since you have multiple classes that can cast spells, you must prepare those spells manually. See 'class info (class name)' to see spell prep commands for your classes.\r\n");
// }
// }

}

Expand Down
8 changes: 6 additions & 2 deletions act.other.c
Original file line number Diff line number Diff line change
Expand Up @@ -4478,6 +4478,10 @@ int can_lore_target(struct char_data *ch, struct char_data *target_ch, struct ob
bool knowledge = FALSE;
int lore_bonus = 0;

// if the object was already identified, it can always be identified again
if (target_obj && OBJ_FLAGGED(target_obj, ITEM_IDENTIFIED))
return TRUE;

/* establish any lore bonus */
if (HAS_FEAT(ch, FEAT_KNOWLEDGE))
{
Expand All @@ -4491,8 +4495,7 @@ int can_lore_target(struct char_data *ch, struct char_data *target_ch, struct ob
}

/* good enough lore for object? */
if (target_obj && GET_OBJ_COST(target_obj) <=
lore_app[(compute_ability(ch, ABILITY_LORE) + lore_bonus)])
if (target_obj && GET_OBJ_COST(target_obj) <= lore_app[(compute_ability(ch, ABILITY_LORE) + lore_bonus)])
{
knowledge = TRUE;
}
Expand Down Expand Up @@ -4570,6 +4573,7 @@ ACMD(do_lore)
/* success! */
if (tobj)
{
SET_BIT_AR(GET_OBJ_EXTRA(tobj), ITEM_IDENTIFIED);
do_stat_object(ch, tobj, ITEM_STAT_MODE_LORE_SKILL);
}
else if (tch)
Expand Down
18 changes: 18 additions & 0 deletions act.wizard.c
Original file line number Diff line number Diff line change
Expand Up @@ -9662,4 +9662,22 @@ ACMD(do_save_objects_to_database)
send_to_char(ch, "Objects successfully exported to database.\r\n");
}

ACMD(do_save_everything)
{
int i = 0;
send_to_char(ch, "You are now saving every zone.\r\n");
for (i = 0; i <= top_of_zone_table; i++)
{
add_to_save_list(zone_table[i].number, SL_WLD);
add_to_save_list(zone_table[i].number, SL_MOB);
add_to_save_list(zone_table[i].number, SL_OBJ);
add_to_save_list(zone_table[i].number, SL_QST);
add_to_save_list(zone_table[i].number, SL_SHP);
add_to_save_list(zone_table[i].number, SL_ZON);
add_to_save_list(zone_table[i].number, SL_ACT);
add_to_save_list(zone_table[i].number, SL_CFG);
add_to_save_list(zone_table[i].number, SL_HLP);
}
}

/* EOF */
Loading

0 comments on commit bfc69f7

Please sign in to comment.