void do_pre_test(struct creature *ch) { struct obj_data *obj = NULL, *next_obj = NULL; for (obj = ch->carrying; obj; obj = next_obj) { next_obj = obj->next_content; extract_obj(obj); } for (int i = 0; i < NUM_WEARS; i++) { if ((obj = GET_EQ(ch, i))) { extract_obj(GET_EQ(ch, i)); } } while (ch->affected) affect_remove(ch, ch->affected); for (obj = ch->in_room->contents; obj; obj = next_obj) { next_obj = obj->next_content; extract_obj(obj); } if (GET_COND(ch, FULL) >= 0) GET_COND(ch, FULL) = 24; if (GET_COND(ch, THIRST) >= 0) GET_COND(ch, THIRST) = 24; SET_BIT(ch->in_room->room_flags, ROOM_NORECALL); }
/* manapoint gain per game hour */ int mana_gain(CharData * ch) { int malnourishCount = 0; struct affected_type *hjp, *next; if (IN_ROOM(ch) == -1) return 0; if(!IS_NPC(ch) && ((GET_COND(ch, HUNGER) == 0 && !IS_VAMPIRE(ch)) || GET_COND(ch, THIRST) == 0)) { if(ch->desc && percentSuccess(2)) { if(!affected_by_spell(ch, SKILL_EMACIATED)) add_affect( ch, ch, SKILL_EMACIATED, GET_LEVEL(ch), 0, 0, -1, 0, FALSE, FALSE, FALSE, FALSE); for (hjp = ch->affected; hjp; hjp = next) { next = hjp->next; if (hjp->type == SKILL_EMACIATED_MANA) malnourishCount++; } if(malnourishCount < 18) add_affect( ch, ch, SKILL_EMACIATED_MANA, GET_LEVEL(ch), APPLY_MANA, -MIN(50, GET_MANA(ch)/20), -1, 0, FALSE, FALSE, FALSE, FALSE); } } int base = calcManaBase(ch); int multiplier = calcManaMulti(ch); int bonus = calcManaBonus(ch); int gain = base*multiplier/100 + bonus; if (affected_by_spell(ch, SKILL_POTENCY)) gain *= 5; return (gain); }
void gain_condition(struct char_data * ch, int condition, int value) { bool intoxicated; if (IS_NPC(ch) || GET_COND(ch, condition) == -1) /* No change */ return; intoxicated = (GET_COND(ch, DRUNK) > 0); GET_COND(ch, condition) += value; GET_COND(ch, condition) = MAX(0, GET_COND(ch, condition)); GET_COND(ch, condition) = MIN(24, GET_COND(ch, condition)); if (GET_COND(ch, condition) || PLR_FLAGGED(ch, PLR_WRITING)) return; switch (condition) { case FULL: send_to_char("You are hungry.\r\n", ch); return; case THIRST: send_to_char("You are thirsty.\r\n", ch); return; case DRUNK: if (intoxicated) send_to_char("You are now sober.\r\n", ch); return; default: break; } }
/* Some initializations for characters, including initial skills */ void do_start(struct char_data *ch) { GET_LEVEL(ch) = 1; GET_TOT_LEVEL(ch) = 1; GET_EXP(ch) = 1; GET_CLASS_1(ch) = GET_CLASS(ch); GET_MULTIS(ch) = 1; set_title(ch, NULL); roll_real_abils(ch); GET_MAX_HIT(ch) = 10; GET_MAX_MANA(ch) = 100; GET_MAX_MOVE(ch) = 100; switch (GET_CLASS(ch)) { case CLASS_ADEPT: break; case CLASS_MEDIC: break; case CLASS_BANDIT: SET_SKILL(ch, SKILL_SNEAK, 10); SET_SKILL(ch, SKILL_HIDE, 5); SET_SKILL(ch, SKILL_STEAL, 15); SET_SKILL(ch, SKILL_BACKSTAB, 10); SET_SKILL(ch, SKILL_PICK_LOCK, 10); SET_SKILL(ch, SKILL_TRACK, 10); break; case CLASS_SOLDIER: break; } advance_level(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, HUNGER) = 24; GET_COND(ch, DRUNK) = 0; if (CONFIG_SITEOK_ALL) SET_BIT_AR(PLR_FLAGS(ch), PLR_SITEOK); }
void do_eat(struct char_data *ch, char *argument, int cmd) { char buf[100]; struct obj_data *temp; struct affected_type af; one_argument(argument,buf); if(!(temp = get_obj_in_list_vis(ch,buf,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if((temp->obj_flags.type_flag != ITEM_FOOD) && (GET_LEVEL(ch) < 22)) { act("Your stomach refuses to eat that!?!",FALSE,ch,0,0,TO_CHAR); return; } if(GET_COND(ch,FULL)>20) /* Stomach full */ { act("You are to full to eat more!",FALSE,ch,0,0,TO_CHAR); return; } act("$n eats $p",TRUE,ch,temp,0,TO_ROOM); act("You eat the $o.",FALSE,ch,temp,0,TO_CHAR); gain_condition(ch,FULL,temp->obj_flags.value[0]); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3] && (GET_LEVEL(ch) < 21)) /* The shit was poisoned ! */ { act("Ooups, it tasted rather strange ?!!?",FALSE,ch,0,0,TO_CHAR); act("$n coughs and utters some strange sounds.",FALSE,ch,0,0,TO_ROOM); af.type = SPELL_POISON; af.duration = temp->obj_flags.value[0]*2; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_join(ch,&af, FALSE, FALSE); } extract_obj(temp); }
int do_pass_remort_test(struct creature *ch) { int i; // Wipe thier skills for (i = 1; i <= MAX_SKILLS; i++) SET_SKILL(ch, i, 0); do_start(ch, false); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOPROJECT | PRF_ROOMFLAGS | PRF_HOLYLIGHT | PRF_NOHASSLE | PRF_LOG1 | PRF_LOG2 | PRF_NOWIZ); REMOVE_BIT(PLR_FLAGS(ch), PLR_HALT | PLR_INVSTART | PLR_MORTALIZED | PLR_OLCGOD); GET_INVIS_LVL(ch) = 0; GET_COND(ch, DRUNK) = 0; GET_COND(ch, FULL) = 0; GET_COND(ch, THIRST) = 0; // Give em another gen if (GET_REMORT_GEN(ch) == 10) account_set_quest_points(ch->account, ch->account->quest_points + 1); else GET_REMORT_GEN(ch)++; // At gen 1 they enter the world of pk, like it or not if (GET_REMORT_GEN(ch) >= 1 && RAW_REPUTATION_OF(ch) <= 0) gain_reputation(ch, 5); // Whack thier remort invis GET_WIMP_LEV(ch) = 0; // wimpy GET_TOT_DAM(ch) = 0; // cyborg damage // Tell everyone that they remorted char *msg = tmp_sprintf("%s completed gen %d remort test", GET_NAME(ch), GET_REMORT_GEN(ch)); mudlog(LVL_IMMORT, BRF, false, "%s", msg); REMOVE_BIT(ch->in_room->room_flags, ROOM_NORECALL); // Save the char and its implants but not its eq creature_remort(ch); return 1; }
void do_taste(struct char_data *ch, char *argument, int cmd) { struct affected_type af; char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; struct obj_data *temp; one_argument(argument,arg); if(!(temp = get_obj_in_list_vis(ch,arg,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if(temp->obj_flags.type_flag==ITEM_DRINKCON) { do_sip(ch,argument,0); return; } if(!(temp->obj_flags.type_flag==ITEM_FOOD)) { act("Taste that?!? Your stomach refuses!",FALSE,ch,0,0,TO_CHAR); return; } act("$n tastes the $o", FALSE, ch, temp, 0, TO_ROOM); act("You taste the $o", FALSE, ch, temp, 0, TO_CHAR); gain_condition(ch,FULL,1); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]&&!IS_AFFECTED(ch,AFF_POISON)) /* The shit was poisoned ! */ { act("Ooups, it did not taste good at all!",FALSE,ch,0,0,TO_CHAR); af.type = SPELL_POISON; af.duration = 2; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_to_char(ch,&af); } temp->obj_flags.value[0]--; if(!temp->obj_flags.value[0]) /* Nothing left */ { act("There is nothing left now.",FALSE,ch,0,0,TO_CHAR); extract_obj(temp); } return; }
/* This function controls the change to maxmove, maxmana, and maxhp for each * class every time they gain a level. */ void advance_level(struct char_data *ch) { int add_hp, add_mana = 0, add_move = 0, i; add_hp = con_app[GET_CON(ch)].hitp; switch (GET_CLASS(ch)) { case CLASS_ADEPT: add_hp += rand_number(3, 8); add_mana = rand_number(GET_LEVEL(ch), (int)(1.5 * GET_LEVEL(ch))); add_mana = MIN(add_mana, 10); add_move = rand_number(0, 2); break; case CLASS_MEDIC: add_hp += rand_number(5, 10); add_mana = rand_number(GET_LEVEL(ch), (int)(1.5 * GET_LEVEL(ch))); add_mana = MIN(add_mana, 10); add_move = rand_number(0, 2); break; case CLASS_BANDIT: add_hp += rand_number(7, 13); add_mana = 0; add_move = rand_number(1, 3); break; case CLASS_SOLDIER: add_hp += rand_number(10, 15); add_mana = 0; add_move = rand_number(1, 3); break; } ch->points.max_hit += MAX(1, add_hp); ch->points.max_move += MAX(1, add_move); if (GET_LEVEL(ch) > 1) ch->points.max_mana += add_mana; if (IS_ADEPT(ch) || IS_MEDIC(ch)) GET_PRACTICES(ch) += MAX(2, wis_app[GET_WIS(ch)].bonus); else GET_PRACTICES(ch) += MIN(2, MAX(1, wis_app[GET_WIS(ch)].bonus)); if (GET_LEVEL(ch) >= LVL_IMMORT) { for (i = 0; i < 3; i++) GET_COND(ch, i) = (char) -1; SET_BIT_AR(PRF_FLAGS(ch), PRF_HOLYLIGHT); } snoop_check(ch); save_char(ch); }
int calcMoveMulti(CharData *ch) { int multi = 100; if(IS_AFFECTED(ch, AFF_PLAGUE) > 0) multi -= 50; /* vampires barely regen vigor in sunlight, unless they're shadow sphered */ if (!IS_NPC(ch) && IS_VAMPIRE(ch) && IS_SUNLIGHT(IN_ROOM(ch)) && !IS_AFFECTED(ch, AFF_SHADOW_SPHERE)) multi -= 90; else if (IS_AFFECTED(ch, AFF_POISON)) multi -= 90; else if ((GET_COND(ch, HUNGER) == 0 && !IS_VAMPIRE(ch)) || (GET_COND(ch, THIRST) == 0)) multi -= 90; if( ROOM_FLAGGED(ch->in_room, ROOM_SUFFER) && ( GET_LEVEL(ch) < LVL_IMMORT )) multi -= 90; else if (!GET_COND(ch, THIRST) && IS_AMARA(ch)) multi -= 90; else if (IS_IZARTI(ch) && IS_EVIL(ch)) multi -= 90; else if (IS_DEMON(ch) && IS_GOOD(ch)) multi -= 90; /* Position calculations */ switch (GET_POS(ch)) { case POS_MEDITATING: case POS_SLEEPING: multi += 120; break; case POS_RESTING: multi += 80; break; case POS_SITTING: multi += 40; /* Divide by 8 */ break; } // Don't let a player's regeneration completely stagnate... multi = MAX(multi, 25); return multi; }
/* Hitpoint gain pr. game hour */ int hit_gain(struct char_data * ch) { int gain; if (IS_NPC(ch)) { /* Neat and fast */ gain = GET_LEVEL(ch); } else { gain = graf(age(ch)->year, 8, 12, 20, 32, 16, 10, 4); /* Class/Level calculations */ /* Skill/Spell calculations */ /* Position calculations */ switch (GET_POS(ch)) { case POS_SLEEPING: gain += (gain / 2); /* Divide by 2 */ break; case POS_RESTING: gain += (gain / 4); /* Divide by 4 */ break; case POS_SITTING: gain += (gain / 8); /* Divide by 8 */ break; } if (IS_MAGIC_USER(ch) || IS_CLERIC(ch)) gain /= 2; /* Ouch. */ if ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0)) gain /= 4; } if (AFF_FLAGGED(ch, AFF_POISON)) gain /= 4; return (gain); }
int calcHitMulti(CharData *ch) { int multi = 100; if (GET_RACE(ch) == RACE_TROLL) multi += 200; /* Trolls regenerate VERY fast. */ if (GET_RACE(ch) == RACE_STROLL) multi += 300; if(IS_AFFECTED(ch, AFF_PLAGUE)) multi -= 50; if (IS_AFFECTED(ch, AFF_POISON) || IS_AFFECTED(ch, AFF_DISEASE)) multi -= 75; if( ROOM_FLAGGED( ch->in_room, ROOM_HEALTH_REGEN )) multi += 50; /* Position calculations */ switch (GET_POS(ch)) { case POS_MEDITATING: case POS_SLEEPING: multi += 120; break; case POS_RESTING: multi += 60; break; } // During the day, vampires have a difficult time regenerating mana if(!IS_NPC(ch) && ((GET_COND(ch, HUNGER) == 0 && !IS_VAMPIRE(ch)) || (GET_COND(ch, THIRST) == 0))) { multi = 25; return multi; } // Don't let a player's regeneration completely stagnate... multi = MAX(multi, 25); return multi; }
void gain_condition(CHAR_DATA * ch, unsigned condition, int value) { if (condition >= ch->player_specials->saved.conditions.size()) { log("SYSERROR : condition=%d (%s:%d)", condition, __FILE__, __LINE__); return; } if (IS_NPC(ch) || GET_COND(ch, condition) == -1) { return; } bool intoxicated = (GET_COND(ch, DRUNK) >= CHAR_DRUNKED); GET_COND(ch, condition) += value; GET_COND(ch, condition) = MAX(0, GET_COND(ch, condition)); GET_COND(ch, condition) = MIN(MAX_COND_VALUE, GET_COND(ch, condition)); if (GET_COND(ch, condition) || PLR_FLAGGED(ch, PLR_WRITING)) return; switch (condition) { case FULL: send_to_char("Вы голодны.\r\n", ch); return; case THIRST: send_to_char("Вас мучает жажда.\r\n", ch); return; case DRUNK: if (intoxicated && GET_COND(ch, DRUNK) < CHAR_DRUNKED) send_to_char("Наконец-то вы протрезвели.\r\n", ch); GET_DRUNK_STATE(ch) = 0; return; default: break; } }
int calcManaMulti(CharData *ch) { int multi = 100; if(ROOM_FLAGGED(ch->in_room, ROOM_MANA_REGEN)) multi += 50; if(IS_AFFECTED(ch, AFF_WRAITHFORM)) multi += 25; if((GET_CLASS(ch) == CLASS_SHADOW_DANCER) && (IS_DARK(ch->in_room) || IS_AFFECTED(ch, AFF_SHADOW_SPHERE))) multi += 50; if(IS_AFFECTED(ch, AFF_POISON)) multi -= 100; if(!IS_NPC(ch)) { if( !IS_NPC(ch) && ROOM_FLAGGED(ch->in_room, ROOM_SUFFER) && ( GET_LEVEL(ch) < LVL_IMMORT )) multi -= 90; else if (!GET_COND(ch, THIRST) && IS_AMARA(ch)) multi -= 90; else if (IS_IZARTI(ch) && IS_EVIL(ch)) multi -= 90; else if (IS_DEMON(ch) && IS_GOOD(ch)) multi -= 90; } if(GET_RACE(ch) == RACE_STROLL) multi += 100; /* Position calculations */ switch (GET_POS(ch)) { case POS_MEDITATING: case POS_SLEEPING: multi += 120; break; case POS_RESTING: multi += 60; break; } multi += (int)GET_SKILL(ch, SKILL_DEVOTION); // Don't let a player's regeneration completely stagnate... multi = MAX(multi, 25); return multi; }
/* Hitpoint gain per game hour */ int hit_gain(CharData * ch) { // Character is messed if (IN_ROOM(ch) == -1) return 0; // Delusion health deflates fairly quickly if(affected_by_spell(ch, SKILL_DELUSION)) return -(GET_MAX_HIT(ch) * spell_level(ch, SKILL_DELUSION) / 9); /* Are they rotting away ? */ if (!IS_NPC(ch) && IS_UNDEAD(ch)) { return ( (GET_LEVEL(ch) < 50) && (ch->desc) ) ? -GET_LEVEL(ch) : 0; } /* Race calculations */ /* vampires don't regenerate in sunlight, unless they're shadow sphered */ if (!IS_NPC(ch) && IS_VAMPIRE(ch) && IS_SUNLIGHT(IN_ROOM(ch)) && !IS_AFFECTED(ch, AFF_SHADOW_SPHERE)) return 0; if(!IS_NPC(ch)) { int suffer = 0; if(ROOM_FLAGGED(ch->in_room, ROOM_SUFFER) && ( GET_LEVEL(ch) < LVL_IMMORT )) suffer = 1; else if(!GET_COND(ch, THIRST) && IS_AMARA(ch)) suffer = 1; else if (IS_IZARTI(ch) && IS_EVIL(ch)) suffer = 1; else if (IS_DEMON(ch) && IS_GOOD(ch)) suffer = 1; if(suffer == 1) { if(percentSuccess(2)) damage(ch, ch, -SUFFER_RATE, TYPE_ROOM_SUFFER); return 0; } } int base = calcHitBase(ch); int multiplier = calcHitMulti(ch); int bonus = calcHitBonus(ch); int gain = base*multiplier/100 + bonus; return (gain); }/* hit_gain */
void suffer_activity(int pulse) { struct char_data *ch, *next_ch; char *desc; char dam_msg1[120] = "msg1 for suffer room not defined, report this to an imm!\r\n"; char dam_msg2[120] = "msg2 for suffer room not defined, report this to an imm!\r\n"; char dam_msg3[120] = "msg3 for suffer room not defined, report this to an imm!\r\n"; char dam_msg4[120] = "msg4 for suffer room not defined, report this to an imm!\r\n"; char death_char[120] = "You drift into coma and die."; char death_room[120] = "$n has drifted into coma and dies."; char suffer_msg[120] = "$n is suffering."; int percent_hp; int min_dam = 10, max_dam = 20, dam_amount; int hot = FALSE, cold = FALSE , dry = FALSE; for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; if (GET_LEVEL(ch) >= LVL_IMMORT) /* Lets not hurt our immortals */ continue; if (IS_NPC(ch)) continue; // I'm adding in a check to make outlaws "suffer" if in a peace room // Added by Sanji if( (ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL) || IN_ARENA(ch) || IS_SET_AR(ROOM_FLAGS((ch)->in_room), ROOM_CLAN)) && (IS_SET_AR(PLR_FLAGS(ch), PLR_HUNTED) || IS_SET_AR(PLR_FLAGS(ch), PLR_THIEF))) { int to_room = 18001; // Samsera center // hurt the little cheater GET_HIT(ch) = MAX(1, GET_HIT(ch) - GET_MAX_HIT(ch)/8); GET_MANA(ch) = MAX(0, GET_MANA(ch) - GET_MAX_MANA(ch)/8); GET_MOVE(ch) = MAX(0, GET_MOVE(ch) - GET_MAX_MOVE(ch)/8); // where to send the victim? //do //{ // to_room = number( 0, top_of_world ); //} while (IS_SET_AR(world[to_room].room_flags, ROOM_PRIVATE) || // IS_SET_AR(world[to_room].room_flags, ROOM_DEATH) || // IS_SET_AR(world[to_room].room_flags, ROOM_PEACEFUL)); // Lets send out a message, more can be added later. // send_to_char("Naughty naughty. No hiding!\r\n", ch); // Time to move the victim char_from_room(ch); char_to_room(ch, real_room(to_room)); look_at_room(ch, 0); } hot = (ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOT)); cold = (ROOM_FLAGGED(IN_ROOM(ch), ROOM_COLD)); dry = (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DRY)); if (!hot && !cold && !dry) continue; /* Getting ready to pull the damage amount out of the extra desc in the room */ if ((desc = find_exdesc("min_dam", world[ch->in_room].ex_description)) != NULL) min_dam = atoi(desc); else min_dam = 0; if ((desc = find_exdesc("max_dam", world[ch->in_room].ex_description)) != NULL) max_dam = atoi(desc); else max_dam = 25; if (max_dam < min_dam) { send_to_char("SYSERR: Max damage lower then Min damage. Report to an Immortal.\r\n", ch); return; } dam_amount = number(min_dam, max_dam); if ((desc = find_exdesc("suffer1", world[ch->in_room].ex_description)) != NULL) sprintf(dam_msg1, "%s", desc); if ((desc = find_exdesc("suffer2", world[ch->in_room].ex_description)) != NULL) sprintf(dam_msg2, "%s", desc); if ((desc = find_exdesc("suffer3", world[ch->in_room].ex_description)) != NULL) sprintf(dam_msg3, "%s", desc); if ((desc = find_exdesc("suffer4", world[ch->in_room].ex_description)) != NULL) sprintf(dam_msg4, "%s", desc); if ((desc = find_exdesc("death_char", world[ch->in_room].ex_description)) != NULL) sprintf(death_char, "%s", desc); if ((desc = find_exdesc("death_room", world[ch->in_room].ex_description)) != NULL) sprintf(death_room, "%s", desc); if ((desc = find_exdesc("suffer_msg", world[ch->in_room].ex_description)) != NULL) sprintf(suffer_msg, "%s", desc); if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_COLD) && IS_AFFECTED(ch, AFF_NO_COLD)) continue; else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOT) && IS_AFFECTED(ch, AFF_NO_HOT)) continue; else if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOT) && IS_AFFECTED(ch, AFF_NO_DRY)) continue; // DUH! added a check for soak if (((ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOT) || ROOM_FLAGGED(IN_ROOM(ch), ROOM_DRY)) && (GET_COND(ch, THIRST) > 0))) GET_COND(ch, THIRST) = 0; if (dam_amount >= GET_HIT(ch)) dam_amount = GET_HIT(ch) + number(4, 7); else act(suffer_msg, FALSE, ch, 0, 0, TO_ROOM); GET_HIT(ch) -= dam_amount; percent_hp = (100 * GET_HIT(ch)) / GET_MAX_HIT(ch); // need a check here to see if the char is still in the room! if ((ROOM_FLAGGED(IN_ROOM(ch), ROOM_HOT)) || (ROOM_FLAGGED(IN_ROOM(ch), ROOM_COLD)) || (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DRY))){ if (percent_hp > 75) send_to_char(dam_msg1, ch); else if (percent_hp > 50) send_to_char(dam_msg2, ch); else if (percent_hp > 30) send_to_char(dam_msg3, ch); else if (percent_hp >= 15) send_to_char(dam_msg4, ch); else if (percent_hp >= 1) { GET_HIT(ch) = number (-3, -5); send_to_char("You have passed out.\r\n", ch); act("$n has passed out and fallen to the ground.", FALSE, ch, 0, 0, TO_ROOM); update_pos(ch); } else { GET_HIT(ch) = number(-7, -10); act(death_char, FALSE, ch, 0, 0, TO_CHAR); act(death_room, FALSE, ch, 0, 0, TO_ROOM); update_pos(ch); GET_MANA(ch) = 1; die(ch, NULL, 0); } } } /* End of for loop */ }
// Create a brand new character struct creature * account_create_char(struct account *account, const char *name) { struct creature *ch; int i; if (chars_available(account) <= 0) return NULL; ch = make_creature(true); ch->player.name = strdup(tmp_capitalize(tmp_tolower(name))); ch->char_specials.saved.idnum = top_player_idnum() + 1; account->chars = g_list_append(account->chars, GINT_TO_POINTER(GET_IDNUM(ch))); sql_exec ("insert into players (idnum, name, account) values (%ld, '%s', %d)", GET_IDNUM(ch), tmp_sqlescape(name), account->id); // New characters shouldn't get old mail. if (has_mail(GET_IDNUM(ch))) { if (purge_mail(GET_IDNUM(ch)) > 0) { errlog("Purging pre-existing mailfile for new character.(%s)", GET_NAME(ch)); } } // *** if this is our first player --- he be God *** if (GET_IDNUM(ch) == 1) { GET_EXP(ch) = 160000000; GET_LEVEL(ch) = LVL_GRIMP; ch->points.max_hit = 666; ch->points.max_mana = 555; ch->points.max_move = 444; GET_HOME(ch) = HOME_MODRIAN; ch->player_specials->saved.load_room = -1; ch->player_specials->saved.home_room = 1204; } else { ch->points.max_hit = 100; ch->points.max_mana = 100; ch->points.max_move = 82; GET_HOME(ch) = HOME_NEWBIE_SCHOOL; ch->player_specials->saved.load_room = -1; ch->player_specials->saved.home_room = -1; } ch->player_specials->rentcode = RENT_CREATING; set_title(ch, ""); ch->player.short_descr = NULL; ch->player.long_descr = NULL; ch->player.description = NULL; ch->player.time.birth = time(NULL); ch->player.time.death = 0; ch->player.time.played = 0; ch->player.time.logon = time(NULL); for (i = 0; i < MAX_SKILLS; i++) ch->player_specials->saved.skills[i] = 0; for (i = 0; i < MAX_WEAPON_SPEC; i++) { ch->player_specials->saved.weap_spec[i].vnum = 0; ch->player_specials->saved.weap_spec[i].level = 0; } ch->player_specials->saved.imm_qp = 0; ch->player_specials->saved.quest_id = 0; ch->player_specials->saved.qlog_level = 0; GET_REMORT_CLASS(ch) = -1; ch->player.weight = 100; ch->player.height = 100; ch->points.hit = GET_MAX_HIT(ch); ch->points.mana = GET_MAX_MANA(ch); ch->points.move = GET_MAX_MOVE(ch); ch->points.armor = 100; SET_BIT(PRF_FLAGS(ch), PRF_DISPHP | PRF_DISPMANA | PRF_DISPMOVE | PRF_AUTOEXIT | PRF_NOSPEW | PRF_NOPLUG); SET_BIT(PRF2_FLAGS(ch), PRF2_AUTO_DIAGNOSE | PRF2_AUTOPROMPT | PRF2_DISPALIGN | PRF2_NEWBIE_HELPER); ch->char_specials.saved.affected_by = 0; ch->char_specials.saved.affected2_by = 0; ch->char_specials.saved.affected3_by = 0; for (i = 0; i < 5; i++) GET_SAVE(ch, i) = 0; GET_COND(ch, FULL) = (GET_LEVEL(ch) == LVL_GRIMP ? -1 : 24); GET_COND(ch, THIRST) = (GET_LEVEL(ch) == LVL_GRIMP ? -1 : 24); GET_COND(ch, DRUNK) = (GET_LEVEL(ch) == LVL_GRIMP ? -1 : 0); POOFIN(ch) = NULL; POOFOUT(ch) = NULL; return ch; }
void do_drink(struct char_data *ch, char *argument, int cmd) { char buf[100]; struct obj_data *temp; struct affected_type af; int amount,i; one_argument(argument,buf); if(!(temp = get_obj_in_list_vis(ch,buf,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if (temp->obj_flags.type_flag!=ITEM_DRINKCON) { act("You can't drink from that!",FALSE,ch,0,0,TO_CHAR); return; } if((GET_COND(ch,DRUNK)>10)&&(GET_COND(ch,THIRST)>0)) /* The pig is drunk */ { act("You simply fail to reach your mouth!", FALSE, ch, 0, 0, TO_CHAR); act("$n tried to drink but missed $s mouth!", TRUE, ch, 0, 0, TO_ROOM); return; } if((GET_COND(ch,FULL)>20)&&(GET_COND(ch,THIRST)>0)) /* Stomach full */ { act("Your stomach can't contain anymore!",FALSE,ch,0,0,TO_CHAR); return; } if (temp->obj_flags.type_flag==ITEM_DRINKCON){ if(temp->obj_flags.value[1]>0) /* Not empty */ { sprintf(buf,"$n drinks %s from $p",drinks[temp->obj_flags.value[2]]); act(buf, TRUE, ch, temp, 0, TO_ROOM); sprintf(buf,"You drink the %s.\n\r",drinks[temp->obj_flags.value[2]]); send_to_char(buf,ch); if (drink_aff[temp->obj_flags.value[2]][DRUNK] > 0 ) amount = (25-GET_COND(ch,THIRST))/drink_aff[temp->obj_flags.value[2]][DRUNK]; else amount = number(3,10); amount = MIN(amount,temp->obj_flags.value[1]); weight_change_object(temp, -amount); /* Subtract amount */ gain_condition(ch,DRUNK,(int)((int)drink_aff [temp->obj_flags.value[2]][DRUNK]*amount)/4); gain_condition(ch,FULL,(int)((int)drink_aff [temp->obj_flags.value[2]][FULL]*amount)/4); gain_condition(ch,THIRST,(int)((int)drink_aff [temp->obj_flags.value[2]][THIRST]*amount)/4); if(GET_COND(ch,DRUNK)>10) act("You feel drunk.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,THIRST)>20) act("You do not feel thirsty.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]) /* The shit was poisoned ! */ { act("Ooups, it tasted rather strange ?!!?",FALSE,ch,0,0,TO_CHAR); act("$n chokes and utters some strange sounds.", TRUE,ch,0,0,TO_ROOM); af.type = SPELL_POISON; af.duration = amount*3; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_join(ch,&af, FALSE, FALSE); } /* empty the container, and no longer poison. */ temp->obj_flags.value[1]-= amount; if(!temp->obj_flags.value[1]) { /* The last bit */ temp->obj_flags.value[2]=0; temp->obj_flags.value[3]=0; name_from_drinkcon(temp); } return; } } act("It's empty already.",FALSE,ch,0,0,TO_CHAR); return; }
// manapoint gain pr. game hour int mana_gain(CHAR_DATA * ch) { int gain = 0, restore = int_app[GET_REAL_INT(ch)].mana_per_tic, percent = 100; int stopmem = FALSE; if (IS_NPC(ch)) { gain = GET_LEVEL(ch); } else { if (!ch->desc || STATE(ch->desc) != CON_PLAYING) return (0); if (!IS_MANA_CASTER(ch)) gain = graf(age(ch)->year, restore - 8, restore - 4, restore, restore + 5, restore, restore - 4, restore - 8); else gain = mana_gain_cs[GET_REAL_INT(ch)]; // Room specification if (LIKE_ROOM(ch)) percent += 25; // Weather specification if (average_day_temp() < -20) percent -= 10; else if (average_day_temp() < -10) percent -= 5; } if (world[IN_ROOM(ch)]->fires) percent += MAX(50, 10 + world[IN_ROOM(ch)]->fires * 5); if (AFF_FLAGGED(ch, AFF_DEAFNESS)) percent += 15; // Skill/Spell calculations // Position calculations if (ch->get_fighting()) percent -= 90; else switch (GET_POS(ch)) { case POS_SLEEPING: if (IS_MANA_CASTER(ch)) { percent += 80; } else { stopmem = TRUE; percent = 0; } break; case POS_RESTING: percent += 45; break; case POS_SITTING: percent += 30; break; case POS_STANDING: break; default: stopmem = TRUE; percent = 0; break; } if (!IS_MANA_CASTER(ch) && (AFF_FLAGGED(ch, AFF_HOLD) || AFF_FLAGGED(ch, AFF_BLIND) || AFF_FLAGGED(ch, AFF_SLEEP) || ((IN_ROOM(ch) != NOWHERE) && IS_DARK(IN_ROOM(ch)) && !can_use_feat(ch, DARK_READING_FEAT)))) { stopmem = TRUE; percent = 0; } if (!IS_NPC(ch)) { if (GET_COND(ch, FULL) == 0) percent -= 50; if (GET_COND(ch, THIRST) == 0) percent -= 25; if (GET_COND(ch, DRUNK) >= CHAR_DRUNKED) percent -= 10; } if (!IS_MANA_CASTER(ch)) percent += GET_MANAREG(ch); if (AFF_FLAGGED(ch, AFF_POISON) && percent > 0) percent /= 4; percent = MAX(0, MIN(250, percent)); gain = gain * percent / 100; return (stopmem ? 0 : gain); }
struct creature * load_player_from_file(const char *path) { struct creature *ch = NULL; char *txt; if (access(path, W_OK)) { errlog("Unable to open xml player file '%s': %s", path, strerror(errno)); return NULL; } xmlDocPtr doc = xmlParseFile(path); if (!doc) { errlog("XML parse error while loading %s", path); return NULL; } xmlNodePtr root = xmlDocGetRootElement(doc); if (!root) { xmlFreeDoc(doc); errlog("XML file %s is empty", path); return NULL; } /* to save memory, only PC's -- not MOB's -- have player_specials */ ch = make_creature(true); ch->player.name = (char *)xmlGetProp(root, (xmlChar *) "name"); ch->char_specials.saved.idnum = xmlGetIntProp(root, "idnum", 0); set_title(ch, ""); ch->player.short_descr = NULL; ch->player.long_descr = NULL; if (ch->points.max_mana < 100) ch->points.max_mana = 100; ch->char_specials.carry_weight = 0; ch->char_specials.carry_items = 0; ch->char_specials.worn_weight = 0; ch->points.armor = 100; ch->points.hitroll = 0; ch->points.damroll = 0; ch->player_specials->saved.speed = 0; // Read in the subnodes for (xmlNodePtr node = root->xmlChildrenNode; node; node = node->next) { if (xmlMatches(node->name, "points")) { ch->points.mana = xmlGetIntProp(node, "mana", 100); ch->points.max_mana = xmlGetIntProp(node, "maxmana", 100); ch->points.hit = xmlGetIntProp(node, "hit", 100); ch->points.max_hit = xmlGetIntProp(node, "maxhit", 100); ch->points.move = xmlGetIntProp(node, "move", 100); ch->points.max_move = xmlGetIntProp(node, "maxmove", 100); } else if (xmlMatches(node->name, "money")) { ch->points.gold = xmlGetIntProp(node, "gold", 0); ch->points.cash = xmlGetIntProp(node, "cash", 0); ch->points.exp = xmlGetIntProp(node, "xp", 0); } else if (xmlMatches(node->name, "stats")) { ch->player.level = xmlGetIntProp(node, "level", 0); ch->player.height = xmlGetIntProp(node, "height", 0); ch->player.weight = xmlGetIntProp(node, "weight", 0); GET_ALIGNMENT(ch) = xmlGetIntProp(node, "align", 0); /*** Temp fix for negative weights ***/ if (ch->player.weight < 0) { calculate_height_weight(ch); } GET_SEX(ch) = 0; char *sex = (char *)xmlGetProp(node, (xmlChar *) "sex"); if (sex != NULL) GET_SEX(ch) = search_block(sex, genders, false); free(sex); GET_RACE(ch) = 0; char *race_name = (char *)xmlGetProp(node, (xmlChar *) "race"); if (race_name != NULL) { struct race *race = race_by_name(race_name, true); if (race != NULL) { GET_RACE(ch) = race->idnum; } } free(race_name); } else if (xmlMatches(node->name, "class")) { GET_OLD_CLASS(ch) = GET_REMORT_CLASS(ch) = GET_CLASS(ch) = -1; char *trade = (char *)xmlGetProp(node, (xmlChar *) "name"); if (trade != NULL) { GET_CLASS(ch) = search_block(trade, class_names, false); free(trade); } trade = (char *)xmlGetProp(node, (xmlChar *) "remort"); if (trade != NULL) { GET_REMORT_CLASS(ch) = search_block(trade, class_names, false); free(trade); } if (IS_CYBORG(ch)) { char *subclass = (char *)xmlGetProp(node, (xmlChar *) "subclass"); if (subclass != NULL) { GET_OLD_CLASS(ch) = search_block(subclass, borg_subchar_class_names, false); free(subclass); } } if (GET_CLASS(ch) == CLASS_MAGE) { ch->player_specials->saved.mana_shield_low = xmlGetLongProp(node, "manash_low", 0); ch->player_specials->saved.mana_shield_pct = xmlGetLongProp(node, "manash_pct", 0); } GET_REMORT_GEN(ch) = xmlGetIntProp(node, "gen", 0); GET_TOT_DAM(ch) = xmlGetIntProp(node, "total_dam", 0); GET_BROKE(ch) = xmlGetIntProp(node, "broken", 0); } else if (xmlMatches(node->name, "time")) { ch->player.time.birth = xmlGetLongProp(node, "birth", 0); ch->player.time.death = xmlGetLongProp(node, "death", 0); ch->player.time.played = xmlGetLongProp(node, "played", 0); ch->player.time.logon = xmlGetLongProp(node, "last", 0); } else if (xmlMatches(node->name, "carnage")) { GET_PKILLS(ch) = xmlGetIntProp(node, "pkills", 0); GET_ARENAKILLS(ch) = xmlGetIntProp(node, "akills", 0); GET_MOBKILLS(ch) = xmlGetIntProp(node, "mkills", 0); GET_PC_DEATHS(ch) = xmlGetIntProp(node, "deaths", 0); RAW_REPUTATION_OF(ch) = xmlGetIntProp(node, "reputation", 0); GET_SEVERITY(ch) = xmlGetIntProp(node, "severity", 0); } else if (xmlMatches(node->name, "attr")) { ch->aff_abils.str = ch->real_abils.str = xmlGetIntProp(node, "str", 0); ch->aff_abils.str = ch->real_abils.str += xmlGetIntProp(node, "stradd", 0) / 10; ch->aff_abils.intel = ch->real_abils.intel = xmlGetIntProp(node, "int", 0); ch->aff_abils.wis = ch->real_abils.wis = xmlGetIntProp(node, "wis", 0); ch->aff_abils.dex = ch->real_abils.dex = xmlGetIntProp(node, "dex", 0); ch->aff_abils.con = ch->real_abils.con = xmlGetIntProp(node, "con", 0); ch->aff_abils.cha = ch->real_abils.cha = xmlGetIntProp(node, "cha", 0); } else if (xmlMatches(node->name, "condition")) { GET_COND(ch, THIRST) = xmlGetIntProp(node, "thirst", 0); GET_COND(ch, FULL) = xmlGetIntProp(node, "hunger", 0); GET_COND(ch, DRUNK) = xmlGetIntProp(node, "drunk", 0); } else if (xmlMatches(node->name, "player")) { GET_WIMP_LEV(ch) = xmlGetIntProp(node, "wimpy", 0); GET_LIFE_POINTS(ch) = xmlGetIntProp(node, "lp", 0); GET_CLAN(ch) = xmlGetIntProp(node, "clan", 0); } else if (xmlMatches(node->name, "home")) { GET_HOME(ch) = xmlGetIntProp(node, "town", 0); GET_HOMEROOM(ch) = xmlGetIntProp(node, "homeroom", 0); GET_LOADROOM(ch) = xmlGetIntProp(node, "loadroom", 0); } else if (xmlMatches(node->name, "quest")) { GET_QUEST(ch) = xmlGetIntProp(node, "current", 0); GET_IMMORT_QP(ch) = xmlGetIntProp(node, "points", 0); GET_QUEST_ALLOWANCE(ch) = xmlGetIntProp(node, "allowance", 0); } else if (xmlMatches(node->name, "bits")) { char *flag = (char *)xmlGetProp(node, (xmlChar *) "flag1"); ch->char_specials.saved.act = hex2dec(flag); free(flag); flag = (char *)xmlGetProp(node, (xmlChar *) "flag2"); ch->player_specials->saved.plr2_bits = hex2dec(flag); free(flag); } else if (xmlMatches(node->name, "frozen")) { ch->player_specials->thaw_time = xmlGetIntProp(node, "thaw_time", 0); ch->player_specials->freezer_id = xmlGetIntProp(node, "freezer_id", 0); } else if (xmlMatches(node->name, "prefs")) { char *flag = (char *)xmlGetProp(node, (xmlChar *) "flag1"); ch->player_specials->saved.pref = hex2dec(flag); free(flag); flag = (char *)xmlGetProp(node, (xmlChar *) "flag2"); ch->player_specials->saved.pref2 = hex2dec(flag); free(flag); flag = (char *)xmlGetProp(node, (xmlChar *) "tongue"); if (flag) GET_TONGUE(ch) = find_tongue_idx_by_name(flag); free(flag); } else if (xmlMatches(node->name, "weaponspec")) { int vnum = xmlGetIntProp(node, "vnum", -1); int level = xmlGetIntProp(node, "level", 0); if (vnum > 0 && level > 0) { for (int i = 0; i < MAX_WEAPON_SPEC; i++) { if (GET_WEAP_SPEC(ch, i).level <= 0) { GET_WEAP_SPEC(ch, i).vnum = vnum; GET_WEAP_SPEC(ch, i).level = level; break; } } } } else if (xmlMatches(node->name, "title")) { char *txt; txt = (char *)xmlNodeGetContent(node); set_title(ch, txt); free(txt); } else if (xmlMatches(node->name, "affect")) { struct affected_type af; init_affect(&af); af.type = xmlGetIntProp(node, "type", 0); af.duration = xmlGetIntProp(node, "duration", 0); af.modifier = xmlGetIntProp(node, "modifier", 0); af.location = xmlGetIntProp(node, "location", 0); af.level = xmlGetIntProp(node, "level", 0); af.aff_index = xmlGetIntProp(node, "index", 0); af.owner = xmlGetIntProp(node, "owner", 0); af.next = NULL; char *instant = (char *)xmlGetProp(node, (xmlChar *) "instant"); if (instant != NULL && strcmp(instant, "yes") == 0) { af.is_instant = 1; } free(instant); char *bits = (char *)xmlGetProp(node, (xmlChar *) "affbits"); af.bitvector = hex2dec(bits); free(bits); affect_to_char(ch, &af); } else if (xmlMatches(node->name, "affects")) { // PCs shouldn't have ANY perm affects if (IS_NPC(ch)) { char *flag = (char *)xmlGetProp(node, (xmlChar *) "flag1"); AFF_FLAGS(ch) = hex2dec(flag); free(flag); flag = (char *)xmlGetProp(node, (xmlChar *) "flag2"); AFF2_FLAGS(ch) = hex2dec(flag); free(flag); flag = (char *)xmlGetProp(node, (xmlChar *) "flag3"); AFF3_FLAGS(ch) = hex2dec(flag); free(flag); } else { AFF_FLAGS(ch) = 0; AFF2_FLAGS(ch) = 0; AFF3_FLAGS(ch) = 0; } } else if (xmlMatches(node->name, "skill")) { char *spellName = (char *)xmlGetProp(node, (xmlChar *) "name"); int index = str_to_spell(spellName); if (index >= 0) { SET_SKILL(ch, index, xmlGetIntProp(node, "level", 0)); } free(spellName); } else if (xmlMatches(node->name, "tongue")) { char *tongue = (char *)xmlGetProp(node, (xmlChar *) "name"); int index = find_tongue_idx_by_name(tongue); if (index >= 0) SET_TONGUE(ch, index, MIN(100, xmlGetIntProp(node, "level", 0))); free(tongue); } else if (xmlMatches(node->name, "alias")) { struct alias_data *alias; CREATE(alias, struct alias_data, 1); alias->type = xmlGetIntProp(node, "type", 0); alias->alias = (char *)xmlGetProp(node, (xmlChar *) "alias"); alias->replacement = (char *)xmlGetProp(node, (xmlChar *) "replace"); if (alias->alias == NULL || alias->replacement == NULL) { free(alias); } else { add_alias(ch, alias); } } else if (xmlMatches(node->name, "description")) { txt = (char *)xmlNodeGetContent(node); ch->player.description = strdup(tmp_gsub(txt, "\n", "\r\n")); free(txt); } else if (xmlMatches(node->name, "poofin")) { POOFIN(ch) = (char *)xmlNodeGetContent(node); } else if (xmlMatches(node->name, "poofout")) { POOFOUT(ch) = (char *)xmlNodeGetContent(node); } else if (xmlMatches(node->name, "immort")) { txt = (char *)xmlGetProp(node, (xmlChar *) "badge"); strncpy(BADGE(ch), txt, 7); BADGE(ch)[7] = '\0'; free(txt); GET_QLOG_LEVEL(ch) = xmlGetIntProp(node, "qlog", 0); GET_INVIS_LVL(ch) = xmlGetIntProp(node, "invis", 0); } else if (xmlMatches(node->name, "rent")) { char *txt; ch->player_specials->rentcode = xmlGetIntProp(node, "code", 0); ch->player_specials->rent_per_day = xmlGetIntProp(node, "perdiem", 0); ch->player_specials->rent_currency = xmlGetIntProp(node, "currency", 0); txt = (char *)xmlGetProp(node, (xmlChar *) "state"); if (txt) ch->player_specials->desc_mode = (enum cxn_state)search_block(txt, desc_modes, false); free(txt); } else if (xmlMatches(node->name, "recentkill")) { struct kill_record *kill; CREATE(kill, struct kill_record, 1); kill->vnum = xmlGetIntProp(node, "vnum", 0); kill->times = xmlGetIntProp(node, "times", 0); GET_RECENT_KILLS(ch) = g_list_prepend(GET_RECENT_KILLS(ch), kill); } else if (xmlMatches(node->name, "grievance")) {
// Hitpoint gain pr. game hour int hit_gain(CHAR_DATA * ch) { int gain = 0, restore = MAX(10, GET_REAL_CON(ch) * 3 / 2), percent = 100; if (IS_NPC(ch)) gain = GET_LEVEL(ch) + GET_REAL_CON(ch); else { if (!ch->desc || STATE(ch->desc) != CON_PLAYING) return (0); if (!AFF_FLAGGED(ch, AFF_NOOB_REGEN)) { gain = graf(age(ch)->year, restore - 3, restore, restore, restore - 2, restore - 3, restore - 5, restore - 7); } else { const double base_hp = std::max(1, PlayerSystem::con_total_hp(ch)); const double rest_time = 80 + 10 * GET_LEVEL(ch); gain = base_hp / rest_time * 60; } // Room specification // if (LIKE_ROOM(ch)) percent += 25; // Weather specification // if (average_day_temp() < -20) percent -= 15; else if (average_day_temp() < -10) percent -= 10; } if (world[IN_ROOM(ch)]->fires) percent += MAX(50, 10 + world[IN_ROOM(ch)]->fires * 5); // Skill/Spell calculations // // Position calculations // switch (GET_POS(ch)) { case POS_SLEEPING: percent += 25; break; case POS_RESTING: percent += 15; break; case POS_SITTING: percent += 10; break; } if (!IS_NPC(ch)) { if (GET_COND(ch, FULL) == 0) percent -= 50; if (GET_COND(ch, THIRST) == 0) percent -= 25; } percent += GET_HITREG(ch); // TODO: перевоткнуть на apply_аффект if (AFF_FLAGGED(ch, AFF_POISON) && percent > 0) percent /= 4; percent = MAX(0, MIN(250, percent)); gain = gain * percent / 100; if (!IS_NPC(ch)) { if (GET_POS(ch) == POS_INCAP || GET_POS(ch) == POS_MORTALLYW) gain = 0; } return (gain); }
/* 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); } }
void gain_condition(CharData * ch, int condition, int value) { bool intoxicated = (GET_COND(ch, DRUNK) > 0); if (GET_COND(ch, condition) == -1) /* No change */ return; GET_COND(ch, condition) += value; GET_COND(ch, condition) = MAX(0, GET_COND(ch, condition)); if(condition == THIRST && IS_VAMPIRE(ch)) GET_COND(ch, condition) = MIN(48, GET_COND(ch, condition)); else GET_COND(ch, condition) = MIN(24, GET_COND(ch, condition)); // Do not spam hungry players who are trying to write. if (PLR_FLAGGED(ch, PLR_WRITING)) return; if( GET_COND(ch, condition) == 2){ switch (condition) { case HUNGER: send_to_char("You begin to experience hunger pangs.\r\n", ch); return; case THIRST: send_to_char("Your mouth is as dry as a desert.\r\n", ch); return; default: return; } } if(GET_COND(ch, condition) >= 1) return; switch (condition) { case HUNGER: send_to_char("Your stomach grumbles loudly.\r\n", ch); return; case THIRST: if (IS_VAMPIRE(ch)) { send_to_char("Your desire for &08blood&00 consumes you.\r\n", ch); return; } else { send_to_char("You are parched.\r\n", ch); return; } case DRUNK: if(intoxicated) send_to_char("You are now sober.\r\n", ch); return; default: break; } }
// move gain pr. game hour // int move_gain(CHAR_DATA * ch) { int gain = 0, restore = GET_REAL_CON(ch) / 2, percent = 100; if (IS_NPC(ch)) gain = GET_LEVEL(ch); else { if (!ch->desc || STATE(ch->desc) != CON_PLAYING) return (0); gain = graf(age(ch)->year, 15 + restore, 20 + restore, 25 + restore, 20 + restore, 16 + restore, 12 + restore, 8 + restore); // Room specification // if (LIKE_ROOM(ch)) percent += 25; // Weather specification // if (average_day_temp() < -20) percent -= 10; else if (average_day_temp() < -10) percent -= 5; } if (world[IN_ROOM(ch)]->fires) percent += MAX(50, 10 + world[IN_ROOM(ch)]->fires * 5); // Class/Level calculations // // Skill/Spell calculations // // Position calculations // switch (GET_POS(ch)) { case POS_SLEEPING: percent += 25; break; case POS_RESTING: percent += 15; break; case POS_SITTING: percent += 10; break; } if (!IS_NPC(ch)) { if (GET_COND(ch, FULL) == 0) percent -= 50; if (GET_COND(ch, THIRST) == 0) percent -= 25; if (!IS_IMMORTAL(ch) && affected_by_spell(ch, SPELL_HIDE)) percent -= 20; if (!IS_IMMORTAL(ch) && affected_by_spell(ch, SPELL_CAMOUFLAGE)) percent -= 30; } percent += GET_MOVEREG(ch); if (AFF_FLAGGED(ch, AFF_POISON) && percent > 0) percent /= 4; percent = MAX(0, MIN(250, percent)); gain = gain * percent / 100; return (gain); }
void do_sip(struct char_data *ch, char *argument, int cmd) { struct affected_type af; char arg[MAX_STRING_LENGTH]; char buf[MAX_STRING_LENGTH]; struct obj_data *temp; one_argument(argument,arg); if(!(temp = get_obj_in_list_vis(ch,arg,ch->carrying))) { act("You can't find it!",FALSE,ch,0,0,TO_CHAR); return; } if(temp->obj_flags.type_flag!=ITEM_DRINKCON) { act("You can't sip from that!",FALSE,ch,0,0,TO_CHAR); return; } if(GET_COND(ch,DRUNK)>10) /* The pig is drunk ! */ { act("You simply fail to reach your mouth!",FALSE,ch,0,0,TO_CHAR); act("$n tries to sip, but fails!",TRUE,ch,0,0,TO_ROOM); return; } if(!temp->obj_flags.value[1]) /* Empty */ { act("But there is nothing in it?",FALSE,ch,0,0,TO_CHAR); return; } act("$n sips from the $o",TRUE,ch,temp,0,TO_ROOM); sprintf(buf,"It tastes like %s.\n\r",drinks[temp->obj_flags.value[2]]); send_to_char(buf,ch); gain_condition(ch,DRUNK,(int)(drink_aff[temp->obj_flags.value[2]][DRUNK]/4)); gain_condition(ch,FULL,(int)(drink_aff[temp->obj_flags.value[2]][FULL]/4)); gain_condition(ch,THIRST,(int)(drink_aff[temp->obj_flags.value[2]][THIRST]/4)); weight_change_object(temp, -1); /* Subtract one unit */ if(GET_COND(ch,DRUNK)>10) act("You feel drunk.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,THIRST)>20) act("You do not feel thirsty.",FALSE,ch,0,0,TO_CHAR); if(GET_COND(ch,FULL)>20) act("You are full.",FALSE,ch,0,0,TO_CHAR); if(temp->obj_flags.value[3]&&!IS_AFFECTED(ch,AFF_POISON)) /* The shit was poisoned ! */ { act("But it also had a strange taste!",FALSE,ch,0,0,TO_CHAR); af.type = SPELL_POISON; af.duration = 3; af.modifier = 0; af.location = APPLY_NONE; af.bitvector = AFF_POISON; affect_to_char(ch,&af); } temp->obj_flags.value[1]--; if(!temp->obj_flags.value[1]) /* The last bit */ { temp->obj_flags.value[2]=0; temp->obj_flags.value[3]=0; name_from_drinkcon(temp); } return; }
char * makedrunk (char *string, struct char_data * ch) { /* This structure defines all changes for a character */ struct drunk_struct drunk[] = { {3, 10, {"a", "a", "a", "A", "aa", "ah", "Ah", "ao", "aw", "oa", "ahhhh"}}, {8, 5, {"b", "b", "b", "B", "B", "vb"}}, {3, 5, {"c", "c", "C", "cj", "sj", "zj"}}, {5, 2, {"d", "d", "D"}}, {3, 3, {"e", "e", "eh", "E"}}, {4, 5, {"f", "f", "ff", "fff", "fFf", "F"}}, {8, 2, {"g", "g", "G"}}, {9, 6, {"h", "h", "hh", "hhh", "Hhh", "HhH", "H"}}, {7, 6, {"i", "i", "Iii", "ii", "iI", "Ii", "I"}}, {9, 5, {"j", "j", "jj", "Jj", "jJ", "J"}}, {7, 2, {"k", "k", "K"}}, {3, 2, {"l", "l", "L"}}, {5, 8, {"m", "m", "mm", "mmm", "mmmm", "mmmmm", "MmM", "mM", "M"}}, {6, 6, {"n", "n", "nn", "Nn", "nnn", "nNn", "N"}}, {3, 6, {"o", "o", "ooo", "ao", "aOoo", "Ooo", "ooOo"}}, {3, 2, {"p", "p", "P"}}, {5, 5, {"q", "q", "Q", "ku", "ququ", "kukeleku"}}, {4, 2, {"r", "r", "R"}}, {2, 5, {"s", "ss", "zzZzssZ", "ZSssS", "sSzzsss", "sSss"}}, {5, 2, {"t", "t", "T"}}, {3, 6, {"u", "u", "uh", "Uh", "Uhuhhuh", "uhU", "uhhu"}}, {4, 2, {"v", "v", "V"}}, {4, 2, {"w", "w", "W"}}, {5, 6, {"x", "x", "X", "ks", "iks", "kz", "xz"}}, {3, 2, {"y", "y", "Y"}}, {2, 9, {"z", "z", "ZzzZz", "Zzz", "Zsszzsz", "szz", "sZZz", "ZSz", "zZ", "Z"}} }; char buf[1024]; /* this should be enough (?) */ char temp; int pos = 0; int randomnum; char debug[256]; if(GET_COND(ch, DRUNK) > 0) /* character is drunk */ { do { temp = toupper(*string); if( (temp >= 'A') && (temp <= 'Z') ) { if(GET_COND(ch, DRUNK) > drunk[(temp - 'A')].min_drunk_level) { randomnum = number(0, (drunk[(temp - 'A')].number_of_rep)); strcpy(&buf[pos], drunk[(temp - 'A')].replacement[randomnum]); pos += strlen(drunk[(temp - 'A')].replacement[randomnum]); } else buf[pos++] = *string; } else { if ((temp >= '0') && (temp <= '9')) { temp = '0' + number(0, 9); buf[pos++] = temp; } else buf[pos++] = *string; } }while (*string++); buf[pos] = '\0'; /* Mark end of the string... */ strcpy(string, buf); return(string); } return (string); /* character is not drunk, just return the string */ }
void save_player_to_file(struct creature *ch, const char *path) { void expire_old_grievances(struct creature *); // Save vital statistics FILE *ouf; char *tmp_path; struct alias_data *cur_alias; int idx; int hit = GET_HIT(ch), mana = GET_MANA(ch), move = GET_MOVE(ch); tmp_path = tmp_sprintf("%s.tmp", path); ouf = fopen(tmp_path, "w"); if (!ouf) { fprintf(stderr, "Unable to open XML player file for save.[%s] (%s)\n", path, strerror(errno)); return; } struct aff_stash *aff_stash = stash_creature_affects(ch); expire_old_grievances(ch); fprintf(ouf, "<creature name=\"%s\" idnum=\"%ld\">\n", GET_NAME(ch), ch->char_specials.saved.idnum); fprintf(ouf, "<points hit=\"%d\" mana=\"%d\" move=\"%d\" maxhit=\"%d\" maxmana=\"%d\" maxmove=\"%d\"/>\n", ch->points.hit, ch->points.mana, ch->points.move, ch->points.max_hit, ch->points.max_mana, ch->points.max_move); fprintf(ouf, "<money gold=\"%" PRId64 "\" cash=\"%" PRId64 "\" xp=\"%d\"/>\n", ch->points.gold, ch->points.cash, ch->points.exp); fprintf(ouf, "<stats level=\"%d\" sex=\"%s\" race=\"%s\" height=\"%d\" weight=\"%f\" align=\"%d\"/>\n", GET_LEVEL(ch), genders[(int)GET_SEX(ch)], race_name_by_idnum(GET_RACE(ch)), GET_HEIGHT(ch), GET_WEIGHT(ch), GET_ALIGNMENT(ch)); fprintf(ouf, "<class name=\"%s\"", class_names[GET_CLASS(ch)]); if (GET_REMORT_CLASS(ch) != CLASS_UNDEFINED) fprintf(ouf, " remort=\"%s\"", class_names[GET_REMORT_CLASS(ch)]); if (GET_REMORT_GEN(ch) > 0) fprintf(ouf, " gen=\"%d\"", GET_REMORT_GEN(ch)); if (IS_CYBORG(ch)) { if (GET_OLD_CLASS(ch) != -1) fprintf(ouf, " subclass=\"%s\"", borg_subchar_class_names[GET_OLD_CLASS(ch)]); if (GET_TOT_DAM(ch)) fprintf(ouf, " total_dam=\"%d\"", GET_TOT_DAM(ch)); if (GET_BROKE(ch)) fprintf(ouf, " broken=\"%d\"", GET_BROKE(ch)); } if (GET_CLASS(ch) == CLASS_MAGE && GET_SKILL(ch, SPELL_MANA_SHIELD) > 0) { fprintf(ouf, " manash_low=\"%ld\" manash_pct=\"%ld\"", ch->player_specials->saved.mana_shield_low, ch->player_specials->saved.mana_shield_pct); } fprintf(ouf, "/>\n"); fprintf(ouf, "<time birth=\"%ld\" death=\"%ld\" played=\"%ld\" last=\"%ld\"/>\n", ch->player.time.birth, ch->player.time.death, ch->player.time.played, ch->player.time.logon); fprintf(ouf, "<carnage pkills=\"%d\" akills=\"%d\" mkills=\"%d\" deaths=\"%d\" reputation=\"%d\"", GET_PKILLS(ch), GET_ARENAKILLS(ch), GET_MOBKILLS(ch), GET_PC_DEATHS(ch), ch->player_specials->saved.reputation); fprintf(ouf, "/>\n"); fprintf(ouf, "<attr str=\"%d\" int=\"%d\" wis=\"%d\" dex=\"%d\" con=\"%d\" cha=\"%d\"/>\n", ch->real_abils.str, ch->real_abils.intel, ch->real_abils.wis, ch->real_abils.dex, ch->real_abils.con, ch->real_abils.cha); fprintf(ouf, "<condition hunger=\"%d\" thirst=\"%d\" drunk=\"%d\"/>\n", GET_COND(ch, FULL), GET_COND(ch, THIRST), GET_COND(ch, DRUNK)); fprintf(ouf, "<player wimpy=\"%d\" lp=\"%d\" clan=\"%d\"/>\n", GET_WIMP_LEV(ch), GET_LIFE_POINTS(ch), GET_CLAN(ch)); if (ch->desc) ch->player_specials->desc_mode = ch->desc->input_mode; if (ch->player_specials->rentcode == RENT_CREATING || ch->player_specials->rentcode == RENT_REMORTING) { fprintf(ouf, "<rent code=\"%d\" perdiem=\"%d\" " "currency=\"%d\" state=\"%s\"/>\n", ch->player_specials->rentcode, ch->player_specials->rent_per_day, ch->player_specials->rent_currency, desc_modes[(int)ch->player_specials->desc_mode]); } else { fprintf(ouf, "<rent code=\"%d\" perdiem=\"%d\" currency=\"%d\"/>\n", ch->player_specials->rentcode, ch->player_specials->rent_per_day, ch->player_specials->rent_currency); } fprintf(ouf, "<home town=\"%d\" homeroom=\"%d\" loadroom=\"%d\"/>\n", GET_HOME(ch), GET_HOMEROOM(ch), GET_LOADROOM(ch)); fprintf(ouf, "<quest"); if (GET_QUEST(ch)) fprintf(ouf, " current=\"%d\"", GET_QUEST(ch)); if (GET_LEVEL(ch) >= LVL_IMMORT) fprintf(ouf, " allowance=\"%d\"", GET_QUEST_ALLOWANCE(ch)); if (GET_IMMORT_QP(ch) != 0) fprintf(ouf, " points=\"%d\"", GET_IMMORT_QP(ch)); fprintf(ouf, "/>\n"); fprintf(ouf, "<bits flag1=\"%" PRIx32 "\" flag2=\"%" PRIx32 "\"/>\n", ch->char_specials.saved.act, ch->player_specials->saved.plr2_bits); if (PLR_FLAGGED(ch, PLR_FROZEN)) { fprintf(ouf, "<frozen thaw_time=\"%d\" freezer_id=\"%d\"/>\n", ch->player_specials->thaw_time, ch->player_specials->freezer_id); } fprintf(ouf, "<prefs flag1=\"%" PRIx32 "\" flag2=\"%" PRIx32 "\" tongue=\"%s\"/>\n", ch->player_specials->saved.pref, ch->player_specials->saved.pref2, tongue_name(GET_TONGUE(ch))); fprintf(ouf, "<affects flag1=\"%" PRIx32 "\" flag2=\"%" PRIx32 "\" flag3=\"%" PRIx32 "\"/>\n", ch->char_specials.saved.affected_by, ch->char_specials.saved.affected2_by, ch->char_specials.saved.affected3_by); for (idx = 0; idx < MAX_WEAPON_SPEC; idx++) { if (GET_WEAP_SPEC(ch, idx).level > 0) fprintf(ouf, "<weaponspec vnum=\"%d\" level=\"%d\"/>\n", GET_WEAP_SPEC(ch, idx).vnum, GET_WEAP_SPEC(ch, idx).level); } if (GET_TITLE(ch) && *GET_TITLE(ch)) { fprintf(ouf, "<title>%s</title>\n", xmlEncodeTmp(GET_TITLE(ch))); } if (GET_LEVEL(ch) >= 50) { fprintf(ouf, "<immort badge=\"%s\" qlog=\"%d\" invis=\"%d\"/>\n", xmlEncodeSpecialTmp(BADGE(ch)), GET_QLOG_LEVEL(ch), GET_INVIS_LVL(ch)); if (POOFIN(ch) && *POOFIN(ch)) fprintf(ouf, "<poofin>%s</poofin>\n", xmlEncodeTmp(POOFIN(ch))); if (POOFOUT(ch) && *POOFOUT(ch)) fprintf(ouf, "<poofout>%s</poofout>\n", xmlEncodeTmp(POOFOUT(ch))); } if (ch->player.description && *ch->player.description) { fprintf(ouf, "<description>%s</description>\n", xmlEncodeTmp(tmp_gsub(tmp_gsub(ch->player.description, "\r\n", "\n"), "\r", ""))); } for (cur_alias = ch->player_specials->aliases; cur_alias; cur_alias = cur_alias->next) fprintf(ouf, "<alias type=\"%d\" alias=\"%s\" replace=\"%s\"/>\n", cur_alias->type, xmlEncodeSpecialTmp(cur_alias->alias), xmlEncodeSpecialTmp(cur_alias->replacement)); for (struct affected_type *cur_aff = aff_stash->saved_affs; cur_aff; cur_aff = cur_aff->next) fprintf(ouf, "<affect type=\"%d\" duration=\"%d\" modifier=\"%d\" location=\"%d\" level=\"%d\" instant=\"%s\" affbits=\"%lx\" index=\"%d\" owner=\"%ld\"/>\n", cur_aff->type, cur_aff->duration, cur_aff->modifier, cur_aff->location, cur_aff->level, (cur_aff->is_instant) ? "yes" : "no", cur_aff->bitvector, cur_aff->aff_index, cur_aff->owner); if (!IS_IMMORT(ch)) { for (idx = 0; idx < MAX_SKILLS; idx++) if (ch->player_specials->saved.skills[idx] > 0) fprintf(ouf, "<skill name=\"%s\" level=\"%d\"/>\n", spell_to_str(idx), GET_SKILL(ch, idx)); write_tongue_xml(ch, ouf); for (GList * it = GET_RECENT_KILLS(ch); it; it = it->next) { struct kill_record *kill = it->data; fprintf(ouf, "<recentkill vnum=\"%d\" times=\"%d\"/>\n", kill->vnum, kill->times); } for (GList * it = GET_GRIEVANCES(ch); it; it = it->next) { struct grievance *grievance = it->data; fprintf(ouf, "<grievance time=\"%lu\" player=\"%d\" reputation=\"%d\" kind=\"%s\"/>\n", (long unsigned)grievance->time, grievance->player_id, grievance->rep, grievance_kind_descs[grievance->grievance]); } } if (IS_PC(ch) && ch->player_specials->tags) { GHashTableIter iter; char *key; g_hash_table_iter_init(&iter, ch->player_specials->tags); while (g_hash_table_iter_next(&iter, (gpointer *)&key, NULL)) { fprintf(ouf, "<tag tag=\"%s\"/>\n", key); } } fprintf(ouf, "</creature>\n"); fclose(ouf); // on success, move temp file on top of the old file rename(tmp_path, path); restore_creature_affects(ch, aff_stash); free(aff_stash); GET_HIT(ch) = MIN(GET_MAX_HIT(ch), hit); GET_MANA(ch) = MIN(GET_MAX_MANA(ch), mana); GET_MOVE(ch) = MIN(GET_MAX_MOVE(ch), move); }
void regen_update( void ) { CharData *i, *next_char; int hit, mana, move; int vivify_level; for( i = character_list; i; i = next_char ) { next_char = i->next; if(affected_by_spell(i, SKILL_EMACIATED) && (GET_COND(i, HUNGER) != 0 || IS_VAMPIRE(i)) && GET_COND(i, THIRST) != 0) { if(!affected_by_spell(i, SKILL_EMACIATED_MANA) && !affected_by_spell(i, SKILL_EMACIATED_HIT)) affect_from_char(i, SKILL_EMACIATED); else if(percentSuccess(4)) { affect_from_char(i, SKILL_EMACIATED_MANA); affect_from_char(i, SKILL_EMACIATED_HIT); } } // Dwarves sober up 3x faster than most races (unless they drink more...) if(IS_DWARF(i) && !number(0, 35)) gain_condition(i, DRUNK, -1); vivify_level = spell_level(i, SPELL_VIVIFY); affect_from_char(i, SPELL_VIVIFY); if(GET_POS(i) <= POS_MEDITATING) { add_affect(i, i, SPELL_VIVIFY, MIN(vivify_level + 1, 100), APPLY_NONE, 0, -1, 0, FALSE, FALSE, FALSE, FALSE); } if(GET_POS(i) >= POS_MORTALLYW) { hit = hit_gain(i); mana = mana_gain(i); move = move_gain(i); if(affected_by_spell(i, SPELL_VIVIFY)) { if(hit > 0) hit += spell_level(i, SPELL_VIVIFY) * GET_MAX_HIT(i)/600; if(mana > 0) mana += spell_level(i, SPELL_VIVIFY) * GET_MAX_MANA(i)/600; if(move > 0) move += spell_level(i, SPELL_VIVIFY) * GET_MAX_MOVE(i)/600; } // Regeneration is increased on pvp holidays. If you're incapactitated, you will // eventually recover. if(pvpHoliday(i)) { if (GET_POS(i) < POS_SLEEPING) hit = 20; else { hit = (hit > 0) ? hit *3 : 20; mana = (mana > 0) ? mana*2 : 40; move = (move > 0) ? move*2 : 40; } } // 72 seconds per tick... if(hit < 0 || GET_HIT(i) < GET_MAX_HIT(i)) { if(hit>0) GET_HIT(i) += hit/72 + (hit % 72 > number(0, 71)? 1:0); else GET_HIT(i) = MAX(GET_HIT(i) + hit/72 + (-hit % 72 > number(0, 71)?-1:0), -9); } else { int surplus = (GET_HIT(i) - GET_MAX_HIT(i)); GET_HIT(i) -= surplus / 72 + (surplus % 72 > number(0, 71)? 1:0); } if(mana>0) GET_MANA(i) = MAX(MIN(GET_MANA(i) + mana/72 + (mana % 72 > number(0, 71)?1:0), GET_MAX_MANA(i)), 0); else GET_MANA(i) = MIN(GET_MANA(i) + mana/72 + (-mana % 72 > number(0, 71)?-1:0), GET_MAX_MANA(i)); if(move>0) GET_MOVE(i) = MIN(GET_MOVE(i) + move/72 + (move % 72 > number(0, 71)?1:0), GET_MAX_MOVE(i)); else GET_MOVE(i) = MAX(MIN(GET_MOVE(i) + move/72 + (-move % 72 > number(0, 71)?-1:0), GET_MAX_MOVE(i)), 0); update_pos(i); } } }
/* * Write the char to the file. * * @param ch the character to be written * @param fp the file to write to */ void fwrite_char( struct char_data *ch, FILE *fp ) { extern struct race_data * races; struct affected_type *paf; int sn, i; fprintf( fp, "#%s\n", IS_NPC( ch ) ? "MOB" : "PLAYER" ); fprintf( fp, "Name %s~\n", GET_NAME(ch) ); fprintf( fp, "ShtDsc %s~\n", GET_SHORT_DESC(ch) ? GET_SHORT_DESC(ch) : "" ); fprintf( fp, "LngDsc %s~\n", GET_LONG_DESC(ch) ? GET_LONG_DESC(ch) : "" ); fprintf( fp, "Dscr %s~\n", GET_DESCRIPTION(ch) ? GET_DESCRIPTION(ch) : "" ); // fprintf( fp, "Prmpt %s~\n", ch->pcdata->prompt ); fprintf( fp, "Sx %d\n", GET_SEX(ch) ); fprintf( fp, "Race %s~\n", races[ (int)GET_RACE(ch) ].name ); fprintf( fp, "Lvl %d\n", GET_LEVEL(ch) ); fprintf( fp, "Trst %d\n", GET_TRUST(ch) ); /* fprintf( fp, "Playd %ld\n", GET_PLAYED(ch) + (int)( time( 0 ) - GET_LOGON(ch) ) ); */ // fprintf( fp, "Note %ld\n", (unsigned long)ch->last_note ); fprintf( fp, "Room %ld\n", ( ch->in_room == NOWHERE && ch->was_in_room ) ? ch->was_in_room : ch->in_room ); fprintf( fp, "HpMnMv %d %d %d %d %d %d\n", GET_HIT(ch), GET_MAX_HIT(ch), GET_MANA(ch), GET_MAX_MANA(ch), GET_MOVE(ch), GET_MAX_MOVE(ch) ); fprintf( fp, "Gold %ld\n", GET_GOLD(ch) ); fprintf( fp, "Exp %ld\n", GET_EXP(ch) ); fprintf( fp, "Act %lld\n", PLR_FLAGS(ch) ); fprintf( fp, "Act2 %lld\n", PLR2_FLAGS(ch) ); fprintf( fp, "Pref %lld\n", PRF_FLAGS(ch) ); fprintf( fp, "Pref2 %lld\n", PRF2_FLAGS(ch) ); fprintf( fp, "AffdBy %lld\n", AFF_FLAGS(ch) ); fprintf( fp, "AffdBy2 %lld\n", AFF2_FLAGS(ch) ); /* Bug fix from Alander */ fprintf( fp, "Pos %d\n", GET_POS(ch) == POS_FIGHTING ? POS_STANDING : GET_POS(ch) ); fprintf( fp, "Prac %d\n", GET_PRACTICES(ch) ); fprintf( fp, "PAlign %d\n", GET_PERMALIGN(ch) ); fprintf( fp, "CAlign %d\n", GET_ALIGNMENT(ch) ); fprintf( fp, "SavThr " ); for ( i = 0; i < NUM_SAVES; i++ ) fprintf( fp, "%d%s", GET_SAVE(ch, i), (i != NUM_SAVES-1 ? ", " : "\n") ); fprintf( fp, "Hitroll %d\n", GET_HITROLL(ch) ); fprintf( fp, "Damroll %d\n", GET_DAMROLL(ch) ); fprintf( fp, "Armr " ); for ( i = 0; i < ARMOR_LIMIT; i++ ) fprintf( fp, "%d%s", GET_AC(ch, i), (i != ARMOR_LIMIT-1 ? ", " : "\n") ); fprintf( fp, "Wimp %d\n", GET_WIMP_LEV(ch) ); if ( IS_NPC( ch ) ) { fprintf( fp, "Vnum %ld\n", GET_MOB_VNUM(ch) ); } else { fprintf( fp, "Paswd %s~\n", GET_PASSWD(ch) ); fprintf( fp, "Poofin %s~\n", POOFIN(ch) ? POOFIN(ch) : "" ); fprintf( fp, "Poofout %s~\n", POOFOUT(ch) ? POOFOUT(ch) : "" ); fprintf( fp, "Ttle %s~\n", GET_TITLE(ch) ? GET_TITLE(ch) : "" ); fprintf( fp, "AtrPrm %d/%d %d %d %d %d %d %d\n", ch->real_abils.str, ch->real_abils.str_add, ch->real_abils.intel, ch->real_abils.wis, ch->real_abils.dex, ch->real_abils.con, ch->real_abils.cha, ch->real_abils.will ); fprintf( fp, "AtrMd %d/%d %d %d %d %d %d %d\n", ch->aff_abils.str, ch->aff_abils.str_add, ch->aff_abils.intel, ch->aff_abils.wis, ch->aff_abils.dex, ch->aff_abils.con, ch->aff_abils.cha, ch->aff_abils.will ); fprintf( fp, "Conditions " ); for ( i = 0; i < MAX_COND; i++ ) fprintf( fp, "%d%s", GET_COND(ch, i), (i != MAX_COND-1 ? ", " : "\n") ); fprintf( fp, "Addictions " ); for ( i = 0; i < MAX_COND; i++ ) fprintf( fp, "%d%s", GET_ADDICT(ch, i), (i != MAX_COND-1 ? ", " : "\n") ); for ( sn = 0; sn < MAX_SKILLS; sn++ ) { if ( skill_name( sn ) && strcmp( skill_name( sn ), "!UNUSED!" ) && GET_SKILL(ch, sn) > 0 ) { fprintf( fp, "Skill %d '%s'\n", GET_SKILL(ch, sn), skill_name( sn ) ); } } } for ( paf = ch->affected; paf; paf = paf->next ) { fprintf( fp, "Afft %18s~ %3d %3d %3d %lld\n", skill_name( paf->type ), paf->duration, paf->modifier, paf->location, paf->bitvector ); } for ( paf = ch->affected2; paf; paf = paf->next ) { fprintf( fp, "Afft2 %18s~ %3d %3d %3d %lld\n", skill_name( paf->type ), paf->duration, paf->modifier, paf->location, paf->bitvector ); } fprintf( fp, "End\n\n" ); return; }
/* * Load a char and inventory into a new ch structure. */ bool load_char_obj( struct descriptor_data * d, const char * name ) { FILE *fp; struct char_data *ch; char strsave [ MAX_INPUT_LENGTH ]; bool found; char sorry_player [] = "********************************************************\n\r" "** One or more of the critical fields in your player **\n\r" "** file were corrupted since you last played. Please **\n\r" "** contact an administrator or programmer to **\n\r" "** investigate the recovery of your characters. **\n\r" "********************************************************\n\r"; char sorry_object [] = "********************************************************\n\r" "** One or more of the critical fields in your player **\n\r" "** file were corrupted leading to the loss of one or **\n\r" "** more of your possessions. **\n\r" "********************************************************\n\r"; char sorry_alias [] = "********************************************************\n\r" "** One or more of the critical fields in your player **\n\r" "** file were corrupted leading to the loss of one or **\n\r" "** more of your aliases. **\n\r" "********************************************************\n\r"; ch = new_character( TRUE ); d->character = ch; GET_DESC(ch) = d; ch->player.name = str_dup( name ); /* ch->pcdata->prompt = str_dup( daPrompt ); ch->last_note = 0; */ strcpy( GET_PASSWD(ch), "" ); POOFIN(ch) = str_dup( "" ); POOFOUT(ch) = str_dup( "" ); GET_TITLE(ch) = str_dup( "" ); GET_STR(ch) = 10; GET_ADD(ch) = 10; GET_INT(ch) = 10; GET_WIS(ch) = 10; GET_DEX(ch) = 10; GET_CON(ch) = 10; GET_CHA(ch) = 10; GET_WILL(ch) = 10; GET_COND(ch, DRUNK) = 48; GET_COND(ch, FULL) = 48; GET_COND(ch, THIRST) = 48; GET_COND(ch, TIRED) = 48; // ch->pcdata->switched = FALSE; found = FALSE; fclose( fpReserve ); /* parsed player file directories by Yaz of 4th Realm */ /* decompress if .gz file exists - Thx Alander */ sprintf( strsave, "%s/%s/%s%s", PLAYER_DIR, player_dir( GET_NAME(ch) ), capitalize( GET_NAME(ch) ), ".gz" ); if ( ( fp = fopen( strsave, "r" ) ) ) { char buf [ MAX_STRING_LENGTH ]; fclose( fp ); sprintf( buf, "gzip -dfq %s", strsave ); system( buf ); } sprintf( strsave, "%s/%s/%s", PLAYER_DIR, player_dir( GET_NAME(ch) ), capitalize( GET_NAME(ch) ) ); if ( ( fp = fopen( strsave, "r" ) ) ) { char buf[ MAX_STRING_LENGTH ]; int iNest; for ( iNest = 0; iNest < MAX_NEST; iNest++ ) rgObjNest[iNest] = NULL; found = TRUE; for ( ; ; ) { char *word; char letter; int status; letter = fread_letter( fp ); if ( letter == '*' ) { fread_to_eol( fp ); continue; } if ( letter != '#' ) { log( "Load_char_obj: # not found." ); break; } word = fread_word_stat( fp, &status ); if ( !str_cmp( word, "PLAYER" ) ) { if ( fread_char ( ch, fp ) ) { sprintf( buf, "Load_char_obj: %s section PLAYER corrupt.\n\r", name ); log( buf ); SEND_TO_Q( sorry_player, d ); /* * In case you are curious, * it is ok to leave ch alone for close_socket * to free. * We want to now kick the bad character out as * what we are missing are MANDATORY fields. -Kahn */ SET_BIT( PRF_FLAGS(ch), PLR_DELETED ); return TRUE; } } else if ( !str_cmp( word, "OBJECT" ) ) { if ( !fread_obj_char( ch, fp ) ) { sprintf( buf, "Load_char_obj: %s section OBJECT corrupt.\n\r", name ); log( buf ); SEND_TO_Q( sorry_object, d ); return FALSE; } } else if ( !str_cmp( word, "ALIAS" ) ) { if ( !fread_alias( ch, fp ) ) { sprintf( buf, "Load_char_obj: %s section ALIAS corrupt.\n\r", name ); log( buf ); SEND_TO_Q( sorry_alias, d ); return FALSE; } } else if ( !str_cmp( word, "END" ) ) break; else { log( "Load_char_obj: bad section." ); break; } } /* for */ fclose( fp ); } fpReserve = fopen( NULL_FILE, "r" ); if ( found ) rent_adjust( d->character ); return found; }
/* * This function controls the change to maxmove, maxmana, and maxhp for * each char_class every time they gain a level. */ void advance_level(struct creature *ch, int8_t keep_internal) { int add_hp[2], add_mana[2], add_move[2], i, char_class; char *msg; add_hp[0] = add_hp[1] = constitution_hitpoint_bonus(GET_CON(ch)); add_mana[0] = add_mana[1] = wisdom_mana_bonus(GET_WIS(ch)); add_move[0] = add_move[1] = MAX(0, GET_CON(ch) - 15); for (i = 0; i < 2; i++) { if (i == 0) char_class = MIN(GET_CLASS(ch), NUM_CLASSES - 1); else char_class = MIN(GET_REMORT_CLASS(ch), NUM_CLASSES - 1); if (char_class < 0) continue; switch (char_class) { case CLASS_MAGIC_USER: add_hp[i] /= 5; add_hp[i] += number(3, 10); add_mana[i] += number(1, 11) + (GET_LEVEL(ch) / 3); add_move[i] += number(1, 3); break; case CLASS_CLERIC: add_hp[i] /= 2; add_hp[i] += number(5, 11); add_mana[i] += number(1, 10) + (GET_LEVEL(ch) / 5); add_move[i] += number(1, 4); break; case CLASS_BARD: add_hp[i] = add_hp[i] / 3; add_hp[i] += number(5, 10); add_mana[i] += number(1, 4) + (GET_LEVEL(ch) / 10); add_move[i] += number(10, 18); break; case CLASS_THIEF: add_hp[i] /= 3; add_hp[i] += number(4, 10); add_mana[i] = add_mana[i] * 3 / 10; add_move[i] += number(2, 6); break; case CLASS_MERCENARY: add_hp[i] += number(6, 14); add_mana[i] = add_mana[i] * 5 / 10; add_mana[i] += number(1, 5) + GET_LEVEL(ch) / 10; add_move[i] += number(3, 9); break; case CLASS_WARRIOR: add_hp[i] += number(10, 15); add_mana[i] = add_mana[i] * 4 / 10; add_mana[i] += number(1, 5); add_move[i] += number(5, 10); break; case CLASS_BARB: add_hp[i] += number(13, 18); add_mana[i] = add_mana[i] * 3 / 10; add_mana[i] += number(0, 3); add_move[i] += number(5, 10); break; case CLASS_KNIGHT: add_hp[i] += number(7, 13); add_mana[i] = add_mana[i] * 7 / 10; add_mana[i] += number(1, 4) + (GET_LEVEL(ch) / 15); add_move[i] += number(3, 8); break; case CLASS_RANGER: add_hp[i] += number(4, 11); add_mana[i] = add_mana[i] * 6 / 10; add_mana[i] += number(1, 6) + (GET_LEVEL(ch) / 8); add_move[i] += number(6, 14); break; case CLASS_PSIONIC: add_hp[i] /= 3; add_hp[i] += number(3, 8); add_mana[i] = add_mana[i] * 6 / 10; add_mana[i] += number(1, 7) + (GET_LEVEL(ch) / 5); add_move[i] += number(2, 6); break; case CLASS_PHYSIC: add_hp[i] /= 4; add_hp[i] += number(4, 9); add_mana[i] = add_mana[i] * 6 / 10; add_mana[i] += number(1, 6) + (GET_LEVEL(ch) / 3); add_move[i] += number(2, 10); break; case CLASS_CYBORG: add_hp[i] /= 2; add_hp[i] += number(6, 14); add_mana[i] = add_mana[i] * 3 / 10; add_mana[i] += number(1, 2) + (GET_LEVEL(ch) / 15); add_move[i] += number(5, 8); break; case CLASS_MONK: add_hp[i] /= 3; add_hp[i] += number(6, 12); add_mana[i] = add_mana[i] * 3 / 10; add_mana[i] += number(1, 2) + (GET_LEVEL(ch) / 22); add_move[i] += number(6, 9); break; default: add_hp[i] /= 2; add_hp[i] += number(5, 16); add_mana[i] = add_mana[i] * 5 / 10; add_mana[i] += number(1, 13) + (GET_LEVEL(ch) / 4); add_move[i] += number(7, 15); break; } } if (IS_RACE(ch, RACE_HALF_ORC) || IS_RACE(ch, RACE_ORC)) { add_move[0] *= 2; add_move[1] *= 2; } ch->points.max_hit += MAX(1, add_hp[0]); ch->points.max_move += MAX(1, add_move[0]); if (GET_LEVEL(ch) > 1) ch->points.max_mana += add_mana[0]; GET_LIFE_POINTS(ch) += (GET_LEVEL(ch) * (GET_WIS(ch) + GET_CON(ch))) / 300; if (PLR_FLAGGED(ch, PLR_HARDCORE)) GET_LIFE_POINTS(ch) += 1; if (IS_REMORT(ch) && GET_REMORT_GEN(ch)) { if (add_hp[0] < 0 || add_hp[1] < 0) { errlog("remort level (%s) add_hp: [0]=%d,[1]=%d", GET_NAME(ch), add_hp[0], add_hp[1]); } ch->points.max_hit += add_hp[1] / 4; ch->points.max_mana += add_mana[1] / 2; ch->points.max_move += add_move[1] / 4; } if (GET_LEVEL(ch) >= LVL_AMBASSADOR) { for (i = 0; i < 3; i++) GET_COND(ch, i) = -1; SET_BIT(PRF_FLAGS(ch), PRF_HOLYLIGHT); SET_BIT(PRF_FLAGS(ch), PRF_NOHASSLE); } if (GET_LEVEL(ch) == 10) SET_BIT(PRF2_FLAGS(ch), PRF2_NEWBIE_HELPER); // special section for improving read_scrolls and use_wands if (CHECK_SKILL(ch, SKILL_READ_SCROLLS) > 10) SET_SKILL(ch, SKILL_READ_SCROLLS, MIN(100, CHECK_SKILL(ch, SKILL_READ_SCROLLS) + MIN(10, number(1, GET_INT(ch) / 2)))); if (CHECK_SKILL(ch, SKILL_USE_WANDS) > 10) SET_SKILL(ch, SKILL_USE_WANDS, MIN(100, CHECK_SKILL(ch, SKILL_USE_WANDS) + MIN(10, number(1, GET_INT(ch) / 2)))); crashsave(ch); int rid = -1; if (ch->in_room != NULL) rid = ch->in_room->number; msg = tmp_sprintf("%s advanced to level %d in room %d%s", GET_NAME(ch), GET_LEVEL(ch), rid, is_tester(ch) ? " <TESTER>" : ""); if (keep_internal) slog("%s", msg); else mudlog(GET_INVIS_LVL(ch), BRF, true, "%s", msg); }