/** days should be scaled by u->number; STUDYDAYS * u->number is one week worth of learning */ void learn_skill(unit *u, skill_t sk, int days) { int leveldays = STUDYDAYS * u->number; int weeks = 0; if (fval(u, UFL_HUNGER)) { days /= 2; } assert(sk >= 0 && sk < MAXSKILLS); if (inject_learn_fun) { inject_learn_fun(u, sk, days); return; } while (days >= leveldays) { ++weeks; days -= leveldays; } if (days > 0 && rng_int() % leveldays < days) { ++weeks; } if (weeks > 0) { increase_skill(u, sk, weeks); } }
/* * Interreact with skills */ void do_cmd_skill() { int sel = 0, start = 0, max; char c; int table[MAX_SKILLS][2]; int i; int wid, hgt; s16b skill_points_save; s32b *skill_values_save; s32b *skill_mods_save; s16b *skill_rates_save; s16b *skill_invest; s32b *skill_bonus; recalc_skills(TRUE); /* Save the screen */ screen_save(); /* Allocate arrays to save skill values */ C_MAKE(skill_values_save, MAX_SKILLS, s32b); C_MAKE(skill_mods_save, MAX_SKILLS, s32b); C_MAKE(skill_rates_save, MAX_SKILLS, s16b); C_MAKE(skill_invest, MAX_SKILLS, s16b); C_MAKE(skill_bonus, MAX_SKILLS, s32b); /* Save skill points */ skill_points_save = p_ptr->skill_points; /* Save skill values */ for (i = 0; i < max_s_idx; i++) { skill_type *s_ptr = &s_info[i]; skill_values_save[i] = s_ptr->value; skill_mods_save[i] = s_ptr->mod; skill_rates_save[i] = s_ptr->rate; skill_invest[i] = 0; } /* Clear the screen */ Term_clear(); /* Initialise the skill list */ init_table(table, &max, FALSE); while (TRUE) { Term_get_size(&wid, &hgt); /* Display list of skills */ recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus); print_skills(table, max, sel, start); /* Wait for user input */ c = inkey(); /* Leave the skill screen */ if (c == ESCAPE) break; /* Expand / collapse list of skills */ else if (c == '\r') { if (s_info[table[sel][0]].dev) s_info[table[sel][0]].dev = FALSE; else s_info[table[sel][0]].dev = TRUE; init_table(table, &max, FALSE); } /* Next page */ else if (c == 'n') { sel += (hgt - 7); if (sel >= max) sel = max - 1; } /* Previous page */ else if (c == 'p') { sel -= (hgt - 7); if (sel < 0) sel = 0; } /* Select / increase a skill */ else { int dir; /* Allow use of numpad / arrow keys / roguelike keys */ dir = get_keymap_dir(c); /* Move cursor down */ if (dir == 2) sel++; /* Move cursor up */ if (dir == 8) sel--; /* Miscellaneous skills cannot be increased/decreased as a group */ if (table[sel][0] == SKILL_MISC) continue; /* Increase the current skill */ if (dir == 6) increase_skill(table[sel][0], skill_invest); /* Decrease the current skill */ if (dir == 4) decrease_skill(table[sel][0], skill_invest); /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ /* Increase the skill */ if (wizard && (c == '+')) skill_bonus[table[sel][0]] += SKILL_STEP; /* Decrease the skill */ if (wizard && (c == '-')) skill_bonus[table[sel][0]] -= SKILL_STEP; /* Contextual help */ if (c == '?') exec_lua(format("ingame_help('select_context', 'skill', '%s')", s_info[table[sel][0]].name + s_name)); ; /* Handle boundaries and scrolling */ if (sel < 0) sel = max - 1; if (sel >= max) sel = 0; if (sel < start) start = sel; if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1; } } /* Some skill points are spent */ if (p_ptr->skill_points != skill_points_save) { /* Flush input as we ask an important and irreversible question */ flush(); /* Ask we can commit the change */ if (msg_box("Save and use these skill values? (y/n)", (int)(hgt / 2), (int)(wid / 2)) != 'y') { /* User declines -- restore the skill values before exiting */ /* Restore skill points */ p_ptr->skill_points = skill_points_save; /* Restore skill values */ for (i = 0; i < max_s_idx; i++) { skill_type *s_ptr = &s_info[i]; s_ptr->value = skill_values_save[i]; s_ptr->mod = skill_mods_save[i]; s_ptr->rate = skill_rates_save[i]; } } } /* Free arrays to save skill values */ C_FREE(skill_values_save, MAX_SKILLS, s32b); C_FREE(skill_mods_save, MAX_SKILLS, s32b); C_FREE(skill_rates_save, MAX_SKILLS, s16b); C_FREE(skill_invest, MAX_SKILLS, s16b); C_FREE(skill_bonus, MAX_SKILLS, s32b); /* Load the screen */ screen_load(); recalc_skills(FALSE); }
/* the main engine of charm spell, and similar */ void effect_charm(struct char_data *ch, struct char_data *victim, int spellnum) { struct affected_type af; int elf_bonus = 0; if (!IS_NPC(victim) && (GET_RACE(victim) == RACE_ELF || //elven enchantment resistance GET_RACE(victim) == RACE_H_ELF)) // added check for IS_NPC because NPCRACE_HUMAN == RACE_ELF and NPCRACE_ABERRATION == RACE_H_ELF elf_bonus += 2; if (victim == ch) send_to_char(ch, "You like yourself even better!\r\n"); else if (MOB_FLAGGED(victim, MOB_NOCHARM)) { send_to_char(ch, "Your victim doesn't seem vulnerable to this " "enchantments!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (IS_AFFECTED(victim, AFF_MIND_BLANK)) { send_to_char(ch, "Your victim is protected from this " "enchantment!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (AFF_FLAGGED(ch, AFF_CHARM)) send_to_char(ch, "You can't have any followers of your own!\r\n"); else if (AFF_FLAGGED(victim, AFF_CHARM)) send_to_char(ch, "Your victim is already charmed.\r\n"); else if (spellnum == SPELL_CHARM && (CASTER_LEVEL(ch) < GET_LEVEL(victim) || GET_LEVEL(victim) >= 8)) send_to_char(ch, "Your victim is too powerful.\r\n"); else if ((spellnum == SPELL_DOMINATE_PERSON || spellnum == SPELL_MASS_DOMINATION) && CASTER_LEVEL(ch) < GET_LEVEL(victim)) send_to_char(ch, "Your victim is too powerful.\r\n"); /* player charming another player - no legal reason for this */ else if (!CONFIG_PK_ALLOWED && !IS_NPC(victim)) send_to_char(ch, "You fail - shouldn't be doing it anyway.\r\n"); else if (circle_follow(victim, ch)) send_to_char(ch, "Sorry, following in circles is not allowed.\r\n"); else if (mag_resistance(ch, victim, 0)) { send_to_char(ch, "You failed to penetrate the spell resistance!"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else if (mag_savingthrow(ch, victim, SAVING_WILL, elf_bonus)) { send_to_char(ch, "Your victim resists!\r\n"); if (IS_NPC(victim)) hit(victim, ch, TYPE_UNDEFINED, DAM_RESERVED_DBC, 0, FALSE); } else { /* slippery mind gives a second save */ if (!IS_NPC(victim) && GET_SKILL(victim, SKILL_SLIPPERY_MIND)) { increase_skill(victim, SKILL_SLIPPERY_MIND); send_to_char(victim, "\tW*Slippery Mind*\tn "); if (mag_savingthrow(ch, victim, SAVING_WILL, 0)) { return; } } if (victim->master) stop_follower(victim); add_follower(victim, ch); new_affect(&af); if (spellnum == SPELL_CHARM) af.spell = SPELL_CHARM; if (spellnum == SPELL_CHARM_ANIMAL) af.spell = SPELL_CHARM_ANIMAL; else if (spellnum == SPELL_DOMINATE_PERSON) af.spell = SPELL_DOMINATE_PERSON; else if (spellnum == SPELL_MASS_DOMINATION) af.spell = SPELL_MASS_DOMINATION; af.duration = 100; if (GET_CHA_BONUS(ch)) af.duration += GET_CHA_BONUS(ch) * 4; SET_BIT_AR(af.bitvector, AFF_CHARM); affect_to_char(victim, &af); act("Isn't $n just such a nice fellow?", FALSE, ch, 0, victim, TO_VICT); // if (IS_NPC(victim)) // REMOVE_BIT_AR(MOB_FLAGS(victim), MOB_SPEC); } // should never get here }
/* * Interreact with skills */ void do_cmd_skill() { s32b sel = 0, start = 0, max, max_ab = 0; s32b c; s32b **table, *table_ab; s32b i; s32b wid, hgt; s16b skill_points_save; s32b *skill_values_save; s32b *skill_mods_save; s16b *skill_rates_save; s16b *skill_invest; s32b *skill_bonus; bool *ab_learned; recalc_skills(TRUE); /* Save the screen */ screen_save(); /* Allocate arrays to save skill values */ C_MAKE(table, max_s_idx, s32b*); for (i = 0; i < max_s_idx; i++) C_MAKE(table[i], 2, s32b); C_MAKE(skill_values_save, max_s_idx, s32b); C_MAKE(skill_mods_save, max_s_idx, s32b); C_MAKE(skill_rates_save, max_s_idx, s16b); C_MAKE(skill_invest, max_s_idx, s16b); C_MAKE(skill_bonus, max_s_idx, s32b); /* Initialise the abilities list */ C_MAKE(ab_learned, max_ab_idx, s32b); C_MAKE(table_ab, max_ab_idx, s32b); for (i = 0; i < max_ab_idx; i++) { ab_learned[i] = ab_info[i].acquired; if (ab_info[i].name && (wizard || (!ab_info[i].hidden && show_ability(i)))) add_sorted_ability(table_ab, &max_ab, i); } /* Save skill points */ skill_points_save = p_ptr->skill_points; /* Save skill values */ for (i = 0; i < max_s_idx; i++) { skill_type *s_ptr = &s_info[i]; skill_values_save[i] = s_ptr->value; skill_mods_save[i] = s_ptr->mod; skill_rates_save[i] = s_ptr->rate; skill_invest[i] = 0; } /* Clear the screen */ Term_clear(); /* Initialise the skill list */ init_table(table, &max, FALSE); if (max) max++; if (max_ab) max_ab++; if (max > 1) sel = 1; while (TRUE) { Term_get_size(&wid, &hgt); /* Display list of skills */ recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus); print_all(table, max, table_ab, max_ab, sel, start); /* Wait for user input */ c = inkey(); /* Leave the skill screen */ if (c == ESCAPE) break; /* Expand / collapse list of skills */ else if ((sel < max) && (sel != 0) && (c == '\r')) { if (s_info[table[sel-1][0]].dev) s_info[table[sel-1][0]].dev = FALSE; else s_info[table[sel-1][0]].dev = TRUE; init_table(table, &max, FALSE); max++; } /* Next page */ else if (c == 'n') { sel += (hgt - 7); if (sel >= max + max_ab) sel = max + max_ab - 1; } /* Previous page */ else if (c == 'p') { sel -= (hgt - 7); if (sel < 0) sel = 0; } /* Select / increase a skill */ else { s32b dir; /* Allow use of numpad / arrow keys / roguelike keys */ dir = get_keymap_dir(c); /* Move cursor down */ if (dir == 2) sel++; /* Move cursor up */ if (dir == 8) sel--; if (sel == 0 || sel == max) { // Nothing } else if (sel < max) { /* Increase the current skill */ if (dir == 6) increase_skill(table[sel-1][0], skill_invest); /* Decrease the current skill */ if (dir == 4) decrease_skill(table[sel-1][0], skill_invest); /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ /* Increase the skill */ if (wizard && (c == '+')) skill_bonus[table[sel-1][0]] += SKILL_STEP; /* Decrease the skill */ if (wizard && (c == '-')) skill_bonus[table[sel-1][0]] -= SKILL_STEP; /* Contextual help */ if (c == '?') exec_lua(format("ingame_help('select_context', 'skill', '%s')", s_info[table[sel-1][0]].name)); } else { /* Gain ability */ if (dir == 6) gain_ability(table_ab[sel-1 - max]); if (dir == 4) ungain_ability(table_ab[sel-1 - max], ab_learned[table_ab[sel-1 - max]]); /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ if (wizard && (c == '+')) ab_info[table_ab[sel-1 - max]].acquired = TRUE; if (wizard && (c == '-')) ab_info[table_ab[sel-1 - max]].acquired = FALSE; /* Contextual help */ if (c == '?') exec_lua(format("ingame_help('select_context', 'ability', '%s')", ab_info[table_ab[sel-1 - max]].name)); } /* Handle boundaries and scrolling */ if (sel < 0) sel = max + max_ab - 1; /* Just in case the skill and ability list is empty */ if (sel < 0) sel = 0; if (sel >= max + max_ab) sel = 0; if (sel < start) start = sel; if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1; } } /* Some skill points are spent */ if (p_ptr->skill_points != skill_points_save) { /* Flush input as we ask an important and irreversible question */ flush(); /* Ask we can commit the change */ if (msg_box("Save and use these skill values? (y/n)", (s32b)(hgt / 2), (s32b)(wid / 2)) != 'y') { /* User declines -- restore the skill values before exiting */ /* Restore skill points */ p_ptr->skill_points = skill_points_save; /* Restore skill values */ for (i = 0; i < max_s_idx; i++) { skill_type *s_ptr = &s_info[i]; s_ptr->value = skill_values_save[i]; s_ptr->mod = skill_mods_save[i]; s_ptr->rate = skill_rates_save[i]; } /* Restore abilities */ for (i = 0; i < max_ab_idx; i++) { ab_info[i].acquired = ab_learned[i]; } } } /* Free arrays to save skill values */ C_FREE(skill_values_save, max_s_idx, s32b); C_FREE(skill_mods_save, max_s_idx, s32b); C_FREE(skill_rates_save, max_s_idx, s16b); C_FREE(skill_invest, max_s_idx, s16b); C_FREE(skill_bonus, max_s_idx, s32b); for (i = 0; i < max_s_idx; i++) C_FREE(table[i], 2, s32b); C_FREE(table, max_s_idx, s32b*); C_FREE(ab_learned, max_ab_idx, s32b); C_FREE(table_ab, max_ab_idx, s32b); /* Load the screen */ screen_load(); recalc_skills(FALSE); }