struct aff_stash * stash_creature_affects(struct creature *ch) { // Save vital statistics struct aff_stash *result = NULL; struct affected_type *cur_aff; int pos; CREATE(result, struct aff_stash, 1); // Remove all spell affects without deleting them result->saved_affs = ch->affected; ch->affected = NULL; for (cur_aff = result->saved_affs; cur_aff; cur_aff = cur_aff->next) affect_modify(ch, cur_aff->location, cur_aff->modifier, cur_aff->bitvector, cur_aff->aff_index, false); for (pos = 0; pos < NUM_WEARS; pos++) { if (GET_EQ(ch, pos)) result->saved_eq[pos] = raw_unequip_char(ch, pos, EQUIP_WORN); if (GET_IMPLANT(ch, pos)) result->saved_impl[pos] = raw_unequip_char(ch, pos, EQUIP_IMPLANT); if (GET_TATTOO(ch, pos)) result->saved_tattoo[pos] = raw_unequip_char(ch, pos, EQUIP_TATTOO); } return result; }
bool save_player_objects_to_file(struct creature *ch, const char *path) { FILE *ouf; char *tmp_path; int idx; tmp_path = tmp_sprintf("%s.new", path); ouf = fopen(tmp_path, "w"); if (!ouf) { fprintf(stderr, "Unable to open XML equipment file for save.[%s] (%s)\n", path, strerror(errno)); return false; } fprintf(ouf, "<objects>\n"); // Save the inventory for (struct obj_data * obj = ch->carrying; obj != NULL; obj = obj->next_content) { save_object_to_xml(obj, ouf); } // Save the equipment for (idx = 0; idx < NUM_WEARS; idx++) { if (GET_EQ(ch, idx)) save_object_to_xml(GET_EQ(ch, idx), ouf); if (GET_IMPLANT(ch, idx)) save_object_to_xml(GET_IMPLANT(ch, idx), ouf); if (GET_TATTOO(ch, idx)) save_object_to_xml(GET_TATTOO(ch, idx), ouf); } fprintf(ouf, "</objects>\n"); fclose(ouf); // on success, move the new object file onto the old one rename(tmp_path, path); return true; }
/* ========================================================================= NAME : use_tattoo() DESCRIPTION: RETURNS : TRUE if a tattoo was used WARNINGS : HISTORY : Created by dlkarnes 970417 OTHER : ========================================================================= */ int use_tattoo( struct char_data *ch ) { void add_follower_quiet(struct char_data *ch, struct char_data *leader); if (ch && !IS_NPC(ch)) { if (TAT_TIMER(ch)) { char mybuf[256]; sprintf(mybuf, "You can't use your tattoo's magick for " "%d more hour%s.\r\n", TAT_TIMER(ch),TAT_TIMER(ch)>1?"s":""); send_to_char(mybuf, ch); return(FALSE); } switch (GET_TATTOO(ch)) { case TATTOO_NONE: send_to_char ("You don't have a tattoo.\r\n", ch); break; case TATTOO_SKULL: { struct char_data *skull = read_mobile(9, VIRTUAL); struct affected_type af; char_to_room(skull, ch->in_room); add_follower_quiet(skull, ch); IS_CARRYING_W(skull) = 0; IS_CARRYING_N(skull) = 0; af.type = SPELL_CHARM; af.duration = 20; af.modifier = 0; af.location = 0; af.bitvector = AFF_CHARM; affect_to_char(skull, &af); act("$n's tattoo glows brightly for a second, and $N appears!", TRUE, ch, 0, skull, TO_ROOM); act("Your tattoo glows brightly for a second, and $N appears!", TRUE, ch, 0, skull, TO_CHAR); } break; case TATTOO_EYE: call_magic(ch, ch, NULL, SPELL_GREATPERCEPT, DEFAULT_WAND_LVL, CAST_WAND); break; case TATTOO_SHIP: call_magic(ch, ch, NULL, SPELL_CHANGE_DENSITY, DEFAULT_WAND_LVL, CAST_WAND); break; case TATTOO_ANGEL: call_magic(ch, ch, NULL, SPELL_BLESS, DEFAULT_WAND_LVL, CAST_WAND); break; default: send_to_char("Your tattoo can't be 'use'd.\r\n", ch); return (FALSE); } TAT_TIMER(ch)=24; } return(FALSE); }
/* ========================================================================= NAME : tattoo_af() DESCRIPTION: add or remove the affects of a tattoo RETURNS : n/a WARNINGS : HISTORY : Created by dlkarnes 970418 OTHER : ========================================================================= */ #define MAX_TAT_AFFECTS 3 /*change if necessary */ void tattoo_af( struct char_data *ch, bool add ) { struct affected_type af[MAX_TAT_AFFECTS]; int i = 0; if (!ch || !GET_TATTOO(ch)) return; for (i = 0; i < MAX_TAT_AFFECTS; i++) { af[i].type = 0; af[i].bitvector = AFF_NOTHING; af[i].modifier = 0; af[i].location = APPLY_NONE; } switch (GET_TATTOO(ch)) { case TATTOO_DRAGON: af[0].location = APPLY_DAMROLL; af[0].modifier = 2; af[1].location = APPLY_STR; af[1].modifier = 2; break; case TATTOO_TIGER: af[0].location = APPLY_DEX; af[0].modifier = 1; af[1].location = APPLY_MOVE; af[1].modifier = 10; break; case TATTOO_TRIBAL: af[0].location = APPLY_DEX; af[0].modifier = 1; break; case TATTOO_WORM: af[0].location = APPLY_DAMROLL; af[0].modifier = 2; break; case TATTOO_SWORDS: af[0].location = APPLY_DAMROLL; af[0].modifier = 1; af[1].location = APPLY_HITROLL; af[1].modifier = 1; break; case TATTOO_EAGLE: af[0].location = APPLY_MOVE; af[0].modifier = 20; break; case TATTOO_HEART: af[0].location = APPLY_HIT; af[0].modifier = 20; break; case TATTOO_STAR: af[0].location = APPLY_MANA; af[0].modifier = 20; break; case TATTOO_SPIDER: af[0].location = APPLY_DEX; af[0].modifier = 3; break; case TATTOO_JYHAD: af[0].location = APPLY_DAMROLL; af[0].modifier = 1; break; case TATTOO_MOM: af[0].location = APPLY_WIS; af[0].modifier = 3; break; case TATTOO_FOX: af[0].location = APPLY_INT; af[0].modifier = 1; break; case TATTOO_OWL: af[0].location = APPLY_WIS; af[0].modifier = 1; break; default: break; } for (i = 0; i < MAX_TAT_AFFECTS; i++) if (af[i].location != APPLY_NONE) affect_modify(ch, af[i].location, af[i].modifier, af[i].bitvector, add); }
/* Some initializations for characters, including initial skills If mode == 0, then act as though the character was entering the game for the first time. Otherwise, act as though the character is being set to that level. */ void do_start(struct creature *ch, int mode) { void advance_level(struct creature *ch, int8_t keep_internal); int8_t new_player = 0; int i; struct obj_data *implant_save[NUM_WEARS]; struct obj_data *tattoo_save[NUM_WEARS]; // remove implant affects for (i = 0; i < NUM_WEARS; i++) { if (GET_IMPLANT(ch, i)) implant_save[i] = raw_unequip_char(ch, i, EQUIP_IMPLANT); else implant_save[i] = NULL; if (GET_TATTOO(ch, i)) tattoo_save[i] = raw_unequip_char(ch, i, EQUIP_TATTOO); else tattoo_save[i] = NULL; } if (GET_EXP(ch) == 0 && !IS_REMORT(ch) && !IS_VAMPIRE(ch)) new_player = true; GET_LEVEL(ch) = 1; GET_EXP(ch) = 1; if (mode) roll_real_abils(ch); for (i = 1; i <= MAX_SKILLS; i++) SET_SKILL(ch, i, 0); if (IS_VAMPIRE(ch)) GET_LIFE_POINTS(ch) = 1; else GET_LIFE_POINTS(ch) = 3 * (GET_WIS(ch) + GET_CON(ch)) / 40; ch->points.max_hit = 20; ch->points.max_mana = 100; ch->points.max_move = 82; if (IS_TABAXI(ch)) { SET_SKILL(ch, SKILL_CLAW, LEARNED(ch)); SET_SKILL(ch, SKILL_BITE, LEARNED(ch)); } if (IS_ELF(ch)) { SET_SKILL(ch, SKILL_ARCHERY, LEARNED(ch)); } switch (GET_CLASS(ch)) { case CLASS_MAGIC_USER: SET_SKILL(ch, SKILL_PUNCH, 10); break; case CLASS_CLERIC: SET_SKILL(ch, SKILL_PUNCH, 10); break; case CLASS_THIEF: SET_SKILL(ch, SKILL_PUNCH, 15); SET_SKILL(ch, SKILL_SNEAK, 10); SET_SKILL(ch, SKILL_HIDE, 5); SET_SKILL(ch, SKILL_STEAL, 15); break; case CLASS_WARRIOR: SET_SKILL(ch, SKILL_PUNCH, 20); break; case CLASS_BARB: SET_SKILL(ch, SKILL_PUNCH, 15); break; case CLASS_PSIONIC: SET_SKILL(ch, SKILL_PUNCH, 10); break; case CLASS_PHYSIC: SET_SKILL(ch, SKILL_PUNCH, 10); break; case CLASS_CYBORG: SET_SKILL(ch, SKILL_PUNCH, 10); break; case CLASS_KNIGHT: SET_SKILL(ch, SKILL_PUNCH, 20); break; case CLASS_RANGER: SET_SKILL(ch, SKILL_PUNCH, 15); GET_MAX_MOVE(ch) += dice(4, 9); break; case CLASS_MONK: SET_SKILL(ch, SKILL_PUNCH, 20); break; case CLASS_MERCENARY: SET_SKILL(ch, SKILL_PUNCH, 20); case CLASS_BARD: SET_SKILL(ch, SKILL_PUNCH, 25); SET_SKILL(ch, SKILL_ARCHERY, 25); break; } if (new_player) { if (PAST_CLASS(GET_CLASS(ch))) { deposit_past_bank(ch->desc->account, 8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch)); ch->points.gold = 8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch); } else if (FUTURE_CLASS(GET_CLASS(ch))) { deposit_future_bank(ch->desc->account, 8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch)); ch->points.cash = 8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch); } // New players do not start with the gown at this point // This has been left in for reference for generic newbie starting gear for the future. // New players start with a hospital gown and items most dear to them /* struct obj_data *gown = read_object(33800); if (gown != NULL) { equip_char(ch, gown, WEAR_ABOUT, EQUIP_WORN); } */ // Good clerics start with a holy symbol on neck if ((GET_CLASS(ch) == CLASS_CLERIC) && IS_GOOD(ch)) { struct obj_data *talisman = read_object(1280); if (talisman != NULL) { equip_char(ch, talisman, WEAR_NECK_1, EQUIP_WORN); } } // Evil clerics start with a holy symbol on hold if ((GET_CLASS(ch) == CLASS_CLERIC) && IS_EVIL(ch)) { struct obj_data *symbol = read_object(1260); if (symbol != NULL) { equip_char(ch, symbol, WEAR_HOLD, EQUIP_WORN); } } // Good knights start with a holy symbol on finger if ((GET_CLASS(ch) == CLASS_KNIGHT) && IS_GOOD(ch)) { struct obj_data *ring = read_object(1287); if (ring != NULL) { equip_char(ch, ring, WEAR_FINGER_L, EQUIP_WORN); } } // Evil knights start with a holy symbol on neck if ((GET_CLASS(ch) == CLASS_KNIGHT) && IS_EVIL(ch)) { struct obj_data *pendant = read_object(1270); if (pendant != NULL) { equip_char(ch, pendant, WEAR_NECK_1, EQUIP_WORN); } } // Bards start with a percussion instrument held, and stringed in inventory if (GET_CLASS(ch) == CLASS_BARD) { struct obj_data *lute = read_object(3218); if (lute != NULL) { obj_to_char(lute, ch); } } set_title(ch, "the complete newbie"); } advance_level(ch, 0); GET_MAX_MOVE(ch) += GET_CON(ch); GET_HIT(ch) = GET_MAX_HIT(ch); GET_MANA(ch) = GET_MAX_MANA(ch); GET_MOVE(ch) = GET_MAX_MOVE(ch); GET_COND(ch, THIRST) = 24; GET_COND(ch, FULL) = 24; GET_COND(ch, DRUNK) = 0; if (new_player) { ch->player.time.played = 0; ch->player.time.logon = time(NULL); } for (i = 0; i < NUM_WEARS; i++) { if (implant_save[i]) equip_char(ch, implant_save[i], i, EQUIP_IMPLANT); if (tattoo_save[i]) equip_char(ch, tattoo_save[i], i, EQUIP_TATTOO); } }