// Modified by SinaC 2001 bool check_one_restriction( CHAR_DATA *ch, RESTR_DATA *restr ) { // Added by SinaC 2000 for restriction on ability //if ( restr->ability_r ) { if ( restr->type == RESTR_ABILITY ) { if ( restr->not_r == FALSE ) { if ( get_ability( ch, restr->sn ) < restr->value ) return FALSE; } else if ( get_ability( ch, restr->sn ) >= restr->value ) return FALSE; } // If not an restriction on ability than it's a restriction on a stat else { // Modified by SinaC 2000 for NOT restriction // >= str, int, wis, dex, con, alig if not_r not set // < if not_r set if ( restr_table[restr->type].bits == NULL ) { if ( restr->not_r == FALSE ) { if ( ch->curattr[restr_attr[restr->type].bit] < restr->value ) return FALSE; } else if ( ch->curattr[restr_attr[restr->type].bit] >= restr->value ) return FALSE; } // = race, sex, etho if not_r not set // != if not_r set else if ( is_stat( restr_table[restr->type].bits ) ) { if ( restr->not_r == FALSE ) { if ( ch->curattr[restr_attr[restr->type].bit] != restr->value ) return FALSE; } else if ( ch->curattr[restr_attr[restr->type].bit] == restr->value ) return FALSE; } // or parts, classes, form if not_r not set // nor if not_r set else { if ( restr->not_r == FALSE ) { if (( ch->curattr[restr_attr[restr->type].bit] & restr->value ) != restr->value) return FALSE; } else if (( ch->curattr[restr_attr[restr->type].bit] & restr->value ) == restr->value) return FALSE; } } return TRUE; }
// Added by SinaC 2003 int find_ability( CHAR_DATA *ch, const char *name, const int type ) { /* finds an ability the character can cast/psi/use/song if possible */ //if (IS_NPC(ch)) // return ability_lookup(name); int found = -1; for ( int sn = 0; sn < MAX_ABILITY; sn++ ) { if (ability_table[sn].name == NULL) break; if ( ability_table[sn].type != type ) continue; if (LOWER(name[0]) == LOWER(ability_table[sn].name[0]) && !str_prefix(name,ability_table[sn].name)) { if ( found == -1) found = sn; /* Modified by Sinac 1997 */ if (get_ability( ch, sn )>0) return sn; } } return found; }
int can_gain_ability( CHAR_DATA *ch, const int sn, const bool creation ) { int learned = get_ability( ch, sn ); int casting = get_casting_level( ch, sn ); //int max_casting_rule = class_max_casting_rule( ch ); // to be continued return 0; }
// Added by SinaC 2001 so, people can teach skills/spells to other void do_teach( CHAR_DATA *ch, const char *argument ) { CHAR_DATA *victim; char arg[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; int sn; argument = one_argument( argument, arg ); argument = one_argument( argument, arg2 ); if ( IS_NPC(ch) && ( IS_AFFECTED( ch, AFF_CHARM ) || ch->master != NULL || ch->leader != NULL ) ) { send_to_char("You can't teach anything.\n\r", ch ); return; } if ( ( victim = get_char_room( ch, arg2 ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if ( IS_NPC( victim ) ) { send_to_char("NPC's are dumb, they can't learn anything.\n\r", ch ); return; } if ( ( sn = ability_lookup( arg ) ) <= 0 ) { send_to_char("That skill/spell doesn't exist!\n\r", ch ); return; } if ( get_ability( ch, sn ) < 95 ) { send_to_charf( ch, "You haven't practiced '%s' enough to teach it.\n\r", ability_table[sn].name ); return; } // get_ability_simple cos' we don't want to take care of victim's level if ( get_ability_simple( victim, sn ) > 0 ) { act("$N already knows '$t'.", ch, ability_table[sn].name, victim, TO_CHAR ); return; } victim->pcdata->ability_info[sn].learned = 1; victim->pcdata->ability_info[sn].casting_level = ability_table[sn].nb_casting_level > 0 ? 1 : 0; victim->pcdata->ability_info[sn].level = URANGE( 1, victim->level, 100 ); act( "$n teachs '$t' to $N.", ch, ability_table[sn].name, victim, TO_NOTVICT ); act( "You teach '$t' to $N.", ch, ability_table[sn].name, victim, TO_CHAR ); act( "$N teachs you '$t'.", victim, ability_table[sn].name, ch, TO_CHAR ); }
/** * \brief Returns whether the player has at least the specified level of an ability. * \param ability The ability to get. * \param level The minimum level to check. * \return \c true if the player has at least this level of the ability. */ bool Equipment::has_ability(Ability ability, int level) const { return get_ability(ability) >= level; }
void *ant_ai() { game_object *o=current_object,*b; if (o->hp()==0) // if we are dead return NULL and get deleted { if (o->state==dead) return NULL; else o->set_state(dead); return true_symbol; } if (o->state==flinch_up || o->state==flinch_down) { o->next_picture(); return true_symbol; } switch (o->aistate()) { case ANT_START : { o->set_state((character_state)S_hanging); if (o->lvars[ANT_hide_flag]) o->set_aistate(ANT_HIDING); else o->set_aistate(ANT_HANGING); } break; case ANT_HIDING : { if ((jrand()%128)==0) the_game->play_sound(S_SCARE_SND,127,o->x,o->y); if (o->otype!=S_HIDDEN_ANT) { o->change_type(S_HIDDEN_ANT); // switch types so noone hurts us. o->set_state(stopped); o->set_aistate(ANT_HIDING); } int fall=0; if (o->total_objects()==0) { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; if (abs(b->x-o->x)<130 && (o->y<b->y)) fall=1; } else if (o->get_object(0)->aistate()!=0) fall=1; if (fall) { o->change_type(S_ANT_ROOF); o->set_state((character_state)S_falling); o->set_aistate(ANT_FALL_DOWN); o->set_targetable(1); } else o->set_targetable(0); } break; case ANT_HANGING : { int fall=0; if ((jrand()%128)==0) the_game->play_sound(S_SCARE_SND,127,o->x,o->y); if (o->lvars[ANT_hide_flag]) o->set_aistate(ANT_HIDING); else { o->set_state((character_state)S_hanging); if (o->total_objects()) { if (o->get_object(0)->aistate()!=0) fall=1; } else { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; if (abs(b->x-o->x)<130 && (o->y<b->y)) fall=1; } if (fall) { o->set_state((character_state)S_fall_start); o->set_aistate(ANT_FALL_DOWN); o->set_targetable(1); } else o->set_targetable(0); } } break; case ANT_FALL_DOWN : { o->set_state((character_state)S_falling); if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; scream_check(o,b); int ret=o->mover(0,0,0); if ((ret&BLOCKED_DOWN) || !can_see(o,o->x,o->y,o->x,o->y+1)) { o->set_state((character_state)S_landing); the_game->play_sound(S_ALAND_SND,127,o->x,o->y); o->set_aistate(ANT_LANDING); } } break; case ANT_LANDING : { if (!o->next_picture()) { int32_t xv=0,yv=2; o->try_move(o->x,o->y,xv,yv,1); if (yv!=0) { o->set_gravity(1); o->set_aistate(ANT_FALL_DOWN); } else { o->set_state(stopped); o->set_aistate(ANT_RUNNING); return (void *)ant_ai; } } } break; case ANT_RUNNING : { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; scream_check(o,b); if ((jrand()%16)==0) o->lvars[ANT_need_to_dodge]=1; if (!ant_dodge(o)) { if ((o->x>b->x && o->direction==-1) || (o->x<b->x && o->direction==1)) { o->next_picture(); if ((jrand()%4)==0 && abs(o->x-b->x)<180 && abs(o->y-b->y)<100 && can_hit_player(o,b)) { o->set_state((character_state)S_weapon_fire); o->set_aistate(ANT_FIRE); } else if (abs(o->x-b->x)<100 && abs(o->y-b->y)<10 && (jrand()%4)==0) o->set_aistate(ANT_POUNCE_WAIT); else if (abs(o->x-b->x)>140 && !ant_congestion(o)) o->set_aistate(ANT_JUMP); else { int32_t xm=o->direction>0 ? get_ability(o->otype,run_top_speed) : -get_ability(o->otype,run_top_speed); int32_t ym=0,new_xm=xm; if (o->state!=running) o->set_state(running); o->try_move(o->x,o->y,new_xm,ym,3); if (new_xm!=xm) // blocked, see if we can climb ramp { new_xm=xm; ym=-abs(xm); o->try_move(o->x,o->y,new_xm,ym,3); if (new_xm==xm) { o->x+=new_xm; o->y+=ym; new_xm=0; ym=abs(xm); // now get back on the ground o->try_move(o->x,o->y,new_xm,ym,3); o->x+=new_xm; o->y+=ym; } else { o->direction=0-o->direction; o->set_aistate(ANT_JUMP); } } else o->x+=new_xm; new_xm=0; ym=10; // see if we should fall o->try_move(o->x,o->y,new_xm,ym,3); if (ym==10) o->set_aistate(ANT_FALL_DOWN); else o->y+=ym; } } else { o->direction=o->x>b->x ? -1 : 1; o->set_aistate(ANT_LANDING); } } } break; case ANT_POUNCE_WAIT : { if (!ant_dodge(o)) { o->set_state((character_state)S_pounce_wait); if (o->aistate_time()>alien_wait_time()) { the_game->play_sound(S_ASLASH_SND,127,o->x,o->y); o->set_state(stopped); o->set_aistate(ANT_JUMP); } } } break; case ANT_JUMP : { o->lvars[ANT_need_to_dodge]=0; if (o->move(o->direction,-1,0)&BLOCKED_DOWN) o->set_aistate(ANT_RUNNING); } break; case ANT_FIRE : { if (!ant_dodge(o)) { if (o->state==S_fire_wait) { if (!o->next_picture() || symbol_value(l_difficulty)==l_extreme) { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; fire_at_player(o,b); o->set_state(stopped); o->set_aistate(ANT_RUNNING); } } else o->set_state((character_state)S_fire_wait); } } break; case ANT_JUMP_ROOF : { o->lvars[ANT_need_to_dodge]=0; o->set_state((character_state)S_jump_up); // o->set_yvel(o->yvel()+1); o->set_xacel(0); int32_t xv=0,yv=o->yvel(); o->y-=31; o->try_move(o->x,o->y,xv,yv,1); o->y+=31+yv; if (yv!=o->yvel()) { if (o->yvel()>0) { o->set_state(stopped); o->set_aistate(ANT_RUNNING); } else { o->set_state((character_state)S_top_walk); o->set_aistate(ANT_ROOF_WALK); } o->set_yvel(0); } } break; case ANT_ROOF_WALK : { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; scream_check(o,b); if (((jrand()%8)==0 && abs(o->x-b->x)<10 && o->y<b->y) || o->lvars[ANT_need_to_dodge]==1) { o->set_gravity(1); o->set_state(run_jump); o->set_aistate(ANT_JUMP); ant_ai(); } else { if ((o->x>b->x && o->direction>0) || (o->x<b->x && o->direction<0)) o->direction=-o->direction; else if (abs(o->x-b->x)<120 && (jrand()%4)==0) { o->set_state((character_state)S_ceil_fire); o->set_aistate(ANT_CEIL_SHOOT); ant_ai(); } else { int speed=o->direction>0 ? get_ability(o->otype,run_top_speed) : -get_ability(o->otype,run_top_speed); if (can_see(o,o->x,o->y-31,o->x+speed,o->y-31) && !can_see(o,o->x+speed,o->y-31,o->x+speed,o->y-32)) { o->x+=speed; if (!o->next_picture()) o->set_state((character_state)S_top_walk); } else o->set_aistate(ANT_FALL_DOWN); } } } break; case ANT_CEIL_SHOOT : { if (!o->next_picture()) { if (player_list->next) b=current_level->attacker(current_object); else b=player_list->m_focus; fire_at_player(o,b); o->set_state((character_state)S_top_walk); o->set_aistate(ANT_ROOF_WALK); } } break; } return true_symbol; }
/** * \brief Returns whether the player has at least the specified level of an ability. * \param ability_name the ability to get * \param level the minimum level to check * \return true if the player has at least this level of the ability */ bool Equipment::has_ability(const std::string& ability_name, int level) const { return get_ability(ability_name) >= level; }
void do_specialize( CHAR_DATA *ch, const char *argument ) { int iClass, iWeapon; // char arg[MAX_INPUT_LENGTH]; if (IS_NPC(ch)){ send_to_char("Mobs can't specialize!\n\r",ch); return; } // find a practicer CHAR_DATA *practicer; for ( practicer = ch->in_room->people; practicer != NULL; practicer = practicer->next_in_room) if (IS_NPC(practicer) && IS_SET(practicer->act,ACT_PRACTICE)) break; if (practicer == NULL || !can_see(ch,practicer)) { send_to_char("You can't do that here.\n\r",ch); return; } // argument = one_argument(argument,arg); // No arg if (argument[0] == 0) { Value *v = get_extra_field( ch, "specialized_weapon" ); if ( v != NULL ) { // extra field found int specialized = v->asInt(); send_to_charf(ch, "You are specialized in %s.\n\r", flag_string(weapon_class,specialized)); } else specialize_syntax( ch ); } // List available classes else if ( !str_cmp( argument, "list" ) ) { bool found = FALSE; char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; buf[0] = '\0'; for ( int i = 0; i < MAX_CLASS; i++ ) { if ( class_table[i].name == NULL ) continue; if ( (1 << i) & ch->bstat(classes) ) continue; // already has that class if ( class_table[i].parent_class == i ) continue; // not a sub-class if ( !check_class_god( i, ch->pcdata->god ) ) continue; // god doesn't like that class if ( !check_class_race( ch, i ) ) continue; // race can't be that class if (class_table[i].parent_class != i // doesn't have parent class && !((1<<class_table[i].parent_class) & ch->bstat(classes)) ) continue; if ( class_table[i].choosable == CLASS_CHOOSABLE_NEVER ) continue; // can't be picked if ( ch->isWildMagic // can't get non-wild magic && IS_SET( class_table[i].type, CLASS_MAGIC ) // class if wild mage && !IS_SET( class_table[i].type, CLASS_WILDABLE ) ) continue; sprintf(buf2," %s\n\r", class_table[i].name ); strcat(buf,buf2); found = TRUE; } if (found) { send_to_char("Available classes to specialize in:\n\r",ch); send_to_char(buf,ch); } else send_to_char("You can't specialize in a class.\n\r", ch ); } // List weapon available weapon else if ( !str_cmp( argument, "weapon" ) ) { if ( get_ability( ch, gsn_specialization ) == 0 ) { send_to_char("You don't know how to specialize in a weapon type.\n\r", ch ); return; } bool found = FALSE; char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; buf[0] = '\0'; for (int type = 0; weapon_table[type].name != NULL; type++) if ( weapon_table[type].gsn != NULL && get_ability( ch, *(weapon_table[type].gsn) ) == 100 ) { found = TRUE; sprintf(buf2," %s\n\r", weapon_table[type].name ); strcat(buf,buf2); } if ( found ) { send_to_char("Available weapons to specialize in:\n\r",ch); send_to_char(buf,ch); } else send_to_char("You are not proficient enough in any weapon type.\n\r", ch ); } // Weapon else if ( ( iWeapon = weapon_lookup(argument) ) >= 0 ) { if ( get_ability( ch, gsn_specialization ) == 0 ) { send_to_char("You don't know how to specialize in a weapon type.\n\r", ch ); return; } if ( weapon_table[iWeapon].gsn && get_ability( ch, *(weapon_table[iWeapon].gsn) ) != 100 ) { send_to_charf(ch,"You are not proficient enough in %s.\n\r", weapon_table[iWeapon].name ); return; } Value *sp = get_extra_field( ch, "specialized_weapon" ); if ( sp != NULL ) { int w = sp->asInt(); send_to_charf(ch,"You already specialized in %s.\n\r", w>=0?weapon_table[w].name:"Unknown" ); return; } // Add an extra field storing in which weapon the player is specialized Value v = add_extra_field( ch, "specialized_weapon" ); v.setValue( weapon_table[iWeapon].type ); send_to_charf(ch,"You are now specialized in %s.\n\r", weapon_table[iWeapon].name ); } // Class else if ( ( iClass = class_lookup(argument, TRUE) ) >= 0 ) { if ((1<<iClass) & ch->bstat(classes)) { send_to_char("Choose a class that you don't already have.\n\r",ch); return; } if ( class_table[iClass].parent_class == iClass ) { send_to_char("This is not a sub-class.\n\r", ch ); return; } if ( !check_class_god( iClass, ch->pcdata->god ) ){ send_to_charf(ch, "%s doesn't allow that class.\n\r", god_name(ch->pcdata->god)); return; } if ( !check_class_race( ch, iClass ) ){ send_to_char( "You can't choose that class because of your race.\n\r", ch ); return; } if ( class_table[iClass].parent_class != iClass && !((1<<class_table[iClass].parent_class) & ch->bstat(classes))) { send_to_char("You can't choose this sub-class because you don't have the parent class.\n\r", ch ); return; } // Added by SinaC 2003 to determine if a class can be picked during creation/multiclass if ( class_table[iClass].choosable == CLASS_CHOOSABLE_NEVER ) { send_to_char("This class cannot be picked.\n\r", ch ); return; } if ( ch->isWildMagic // can't get non-wild magic class && IS_SET( class_table[iClass].type, CLASS_MAGIC ) // if wild mage && !IS_SET( class_table[iClass].type, CLASS_WILDABLE ) ) { send_to_charf(ch,"This class cannot be picked by a wild-mage.\n\r"); return; } // Remove parent class REMOVE_BIT( ch->bstat(classes), 1<<class_table[iClass].parent_class ); // Add sub-class SET_BIT( ch->bstat(classes), 1<<iClass ); send_to_charf(ch,"You specialize yourself as %s.\n\r", class_table[iClass].name ); recompute(ch); } else specialize_syntax(ch); }