int cast_mtrigger(char_data *actor, char_data *ch, int spellnum) { trig_data *t; char buf[MAX_INPUT_LENGTH]; if (ch == NULL) return 1; if (!SCRIPT_CHECK(ch, MTRIG_CAST) || AFF_FLAGGED(ch, AFF_CHARM)) return 1; for (t = TRIGGERS(SCRIPT(ch)); t; t = t->next) { if (TRIGGER_CHECK(t, MTRIG_CAST) && (rand_number(1, 100) <= GET_TRIG_NARG(t))) { ADD_UID_VAR(buf, t, actor, "actor", 0); sprintf(buf, "%d", spellnum); add_var(&GET_TRIG_VARS(t), "spell", buf, 0); add_var(&GET_TRIG_VARS(t), "spellname", skill_name(spellnum), 0); return script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); } } return 1; }
void fight_mtrigger(char_data *ch) { struct char_data *actor; trig_data *t; char buf[MAX_INPUT_LENGTH]; if (!SCRIPT_CHECK(ch, MTRIG_FIGHT) || !FIGHTING(ch) || AFF_FLAGGED(ch, AFF_CHARM)) return; for (t = TRIGGERS(SCRIPT(ch)); t; t = t->next) { if (TRIGGER_CHECK(t, MTRIG_FIGHT) && (rand_number(1, 100) <= GET_TRIG_NARG(t))) { actor = FIGHTING(ch); if (actor) ADD_UID_VAR(buf, t, actor, "actor", 0); else add_var(&GET_TRIG_VARS(t), "actor", "nobody", 0); script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); break; } } }
/* move gain pr. game hour */ int move_gain(struct char_data * ch) { int gain; if (IS_NPC(ch)) { /* Neat and fast */ gain = GET_LEVEL(ch); } else { gain = graf(age(ch)->year, 16, 20, 24, 20, 16, 12, 10); /* 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 ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0)) gain /= 4; } if (AFF_FLAGGED(ch, AFF_POISON)) gain /= 4; return (gain); }
int is_tell_ok(Character *ch, Character *vict) { if( ch->IsPurged() ) return FALSE; else if( vict->IsPurged() ) ch->send(NOPERSON); else if(GET_RACE(vict) != GET_RACE(ch) && GET_LEVEL(ch) < LVL_IMMORT && GET_LEVEL(vict) < LVL_IMMORT && !IS_NPC(ch)) ch->send(NOPERSON); else if (ch == vict) ch->send("You try to tell yourself something.\r\n"); else if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOTELL)) ch->send("You can't tell other people while you have notell on.\r\n"); else if ( AFF_FLAGGED(ch, AFF_SILENCE) && GET_LEVEL(ch) <= LVL_IMMORT ) ch->send("You try to speak, but nothing comes out!\r\n"); /*else if(ch->in_room == ch->StartRoom() && GET_LEVEL(ch) < LVL_IMMORT && GET_LEVEL(vict) < LVL_IMMORT && GET_LEVEL(ch) > 5) ch->send("Your attempt to communicate into the Pattern fails.\r\n");*/ // else if(vict->in_room == vict->StartRoom() && GET_LEVEL(vict) < LVL_IMMORT && GET_LEVEL(ch) < LVL_IMMORT) // ch->send("Your attempt to communicate outside of the Pattern fails.\r\n"); else if (ROOM_FLAGGED(ch->in_room, ROOM_SOUNDPROOF)) ch->send("The walls seem to absorb your words.\r\n"); else if (!IS_NPC(vict) && !vict->desc) /* linkless */ Act("$E's linkless at the moment.", FALSE, ch, 0, vict, TO_CHAR | TO_SLEEP); else if (PRF_FLAGGED(ch, PRF_TELL_MUTE)) ch->send("You are mute to tells. You need an immortal to remove this.\r\n"); else if (PRF_FLAGGED(vict, PRF_TELL_MUTE)) Act("$E's is mute to tells... Try again later.", FALSE, ch, 0, vict, TO_CHAR | TO_SLEEP); else if (PLR_FLAGGED(vict, PLR_WRITING)) Act("$E's writing a message right now; try again later.", FALSE, ch, 0, vict, TO_CHAR | TO_SLEEP); else if ((!IS_NPC(vict) && PRF_FLAGGED(vict, PRF_NOTELL)) || ROOM_FLAGGED(vict->in_room, ROOM_SOUNDPROOF) || vict->IsIgnoring(GET_NAME(ch))) Act("$E can't hear you.", FALSE, ch, 0, vict, TO_CHAR | TO_SLEEP); else return TRUE; return FALSE; }
/* simple function to determine if char can walk on water */ int has_boat(struct char_data *ch) { struct obj_data *obj; int i; if (GET_LEVEL(ch) > LVL_IMMORT) return (1); if (AFF_FLAGGED(ch, AFF_WATERWALK)) return (1); if(IS_NPC_FISH(ch)) { return 1; } if(IS_NPC_LIVESTOCK(ch)) { if(ch->master) { if(has_boat(ch->master)) { return 1; } } } /* non-wearable boats in inventory will do it */ for (obj = ch->carrying; obj; obj = obj->next_content) if (GET_OBJ_TYPE(obj) == ITEM_BOAT && (find_eq_pos(ch, obj, NULL) < 0)) return (1); /* and any boat you're wearing will do it too */ for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i) && GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_BOAT) return (1); return (0); }
int receive_mtrigger(char_data *ch, char_data *actor, obj_data *obj) { trig_data *t; char buf[MAX_INPUT_LENGTH]; int ret_val; if (!SCRIPT_CHECK(ch, MTRIG_RECEIVE) || AFF_FLAGGED(ch, AFF_CHARM)) return 1; for (t = TRIGGERS(SCRIPT(ch)); t; t = t->next) { if (TRIGGER_CHECK(t, MTRIG_RECEIVE) && (rand_number(1, 100) <= GET_TRIG_NARG(t))) { ADD_UID_VAR(buf, t, actor, "actor", 0); ADD_UID_VAR(buf, t, obj, "object", 0); ret_val = script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); if (DEAD(actor) || DEAD(ch) || obj->carried_by != actor) return 0; else return ret_val; } } return 1; }
void affect_from_char_II(struct char_data * ch, int skill, int type, int action) { struct affected_type *aff, *next; struct affected_type *temp; struct affected_type af[3]; int i, k; bool accum_affect = FALSE, accum_duration = FALSE; for (aff = ch->affected; aff; aff = next) { next = aff->next; if (aff->type == type) { affect_modify(ch, aff->location, aff->modifier, aff->bitvector, FALSE); REMOVE_FROM_LIST(aff, ch->affected, next); free(aff); affect_total(ch); } } if (action == 2) { switch (skill) { case SPELL_POLYMORPH: if (PLR_FLAGGED(ch, PLR_RABBIT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_RABBIT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing, and your ears shrinking. You no longer feel like a rabbit.\r\n", ch); act("$n's body grows, $s ears shrinking. $n no longer looks like a rabbit.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BIRD)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BIRD); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing and your feathers falling away. You no longer feel like a bird.\r\n", ch); act("$n's body grows, $s feathers falling away as it expands. $n no longer looks like a bird.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_WOLF)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_WOLF); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your your fur shed and your teeth shrink. You no longer feel like a wolf.\r\n", ch); act("$n's teeth shrink, $s fur shedding. $n no longer looks like a wolf.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BEAR)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BEAR); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("Your claws shrink as does the rest of your body. You no longer feel like a bear.\r\n", ch); act("$n's claws shrink as does the rest of $s body. $n no longer looks like a bear.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_CAT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_CAT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your body growing, and your fur shedding. You no longer feel like a cat.\r\n", ch); act("$n's body slowly grows, $s fur shedding. $n no longer looks like a cat.\r\n", 0, ch, 0, 0, TO_ROOM); } for (k = 0; k < NUM_WEARS; k++) if (GET_EQ(ch, k)){ GET_OBJ_DISGUISE(GET_EQ(ch, k)) = 0; } if (affected_by_spell(ch, SPELL_FLIGHT)) affect_from_char_II(ch, SPELL_FLIGHT, SPELL_FLIGHT, 1); if (affected_by_spell(ch, SPELL_HASTE)) affect_from_char_II(ch, SPELL_HASTE, SPELL_HASTE, 1); break; case SKILL_STANCE: if (!AFF_FLAGGED(ch, AFF_TIRED)) { for (i = 0; i < 3; i++) { af[0].type = SPELL_DONTUSEME; af[0].location = APPLY_HITROLL; af[0].modifier = 2; af[0].duration = 7; af[0].bitvector = AFF_STANCE; af[1].type = SPELL_DONTUSEME; af[1].location = APPLY_AC; af[1].modifier = -50; af[1].duration = 7; af[1].bitvector = AFF_STANCE; af[2].type = SPELL_DONTUSEME; af[2].location = APPLY_STR; af[2].modifier = 2; af[2].duration = 7; af[2].bitvector = AFF_STANCE; if (af[i].bitvector || (af[i].location != APPLY_NONE)) { affect_join(ch, af+i, accum_duration, FALSE, accum_affect, FALSE); } } } break; default: break; } } }
// 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); }
void mag_summons(int level, struct char_data *ch, struct obj_data *obj, int spellnum, int savetype) { struct char_data *mob = NULL; struct obj_data *tobj, *next_obj; int pfail = 0, msg = 0, fmsg = 0, num = 1, handle_corpse = FALSE, i; mob_vnum mob_num; if (ch == NULL) return; switch (spellnum) { case SPELL_CLONE: msg = 10; fmsg = rand_number(2, 6); /* Random fail message. */ mob_num = MOB_CLONE; pfail = 50; /* 50% failure, should be based on something later. */ break; case SPELL_ANIMATE_DEAD: if (obj == NULL || !IS_CORPSE(obj)) { act(mag_summon_fail_msgs[7], FALSE, ch, 0, 0, TO_CHAR); return; } handle_corpse = TRUE; msg = 11; fmsg = rand_number(2, 6); /* Random fail message. */ mob_num = MOB_ZOMBIE; pfail = 10; /* 10% failure, should vary in the future. */ break; default: return; } if (AFF_FLAGGED(ch, AFF_CHARM)) { send_to_char(ch, "You are too giddy to have any followers!\r\n"); return; } if (rand_number(0, 101) < pfail) { send_to_char(ch, "%s", mag_summon_fail_msgs[fmsg]); return; } for (i = 0; i < num; i++) { if (!(mob = read_mobile(mob_num, VIRTUAL))) { send_to_char(ch, "You don't quite remember how to make that creature.\r\n"); return; } char_to_room(mob, IN_ROOM(ch)); IS_CARRYING_W(mob) = 0; IS_CARRYING_N(mob) = 0; SET_BIT(AFF_FLAGS(mob), AFF_CHARM); if (spellnum == SPELL_CLONE) { /* Don't mess up the prototype; use new string copies. */ mob->player.name = strdup(GET_NAME(ch)); mob->player.short_descr = strdup(GET_NAME(ch)); } act(mag_summon_msgs[msg], FALSE, ch, 0, mob, TO_ROOM); add_follower(mob, ch); } if (handle_corpse) { for (tobj = obj->contains; tobj; tobj = next_obj) { next_obj = tobj->next_content; obj_from_obj(tobj); obj_to_char(tobj, mob); } extract_obj(obj); } }
/* * Alert: As of bpl14, this function returns the following codes: * < 0 Victim died. * = 0 No damage. * > 0 How much damage done. */ int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype) { if (GET_POS(victim) <= POS_DEAD) { /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */ if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET)) return (-1); log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.", GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch)); die(victim); return (-1); /* -je, 7/7/92 */ } /* peaceful rooms */ if (ch != victim && ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL)) { send_to_char(ch, "This room just has such a peaceful, easy feeling...\r\n"); return (0); } /* shopkeeper protection */ if (!ok_damage_shopkeeper(ch, victim)) return (0); /* You can't damage an immortal! */ if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT)) dam = 0; if (victim != ch) { /* Start the attacker fighting the victim */ if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL)) set_fighting(ch, victim); /* Start the victim fighting the attacker */ if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL)) { set_fighting(victim, ch); if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch)) remember(victim, ch); } } /* If you attack a pet, it hates your guts */ if (victim->master == ch) stop_follower(victim); /* If the attacker is invisible, he becomes visible */ if (AFF_FLAGGED(ch, AFF_INVISIBLE | AFF_HIDE)) appear(ch); /* Cut damage in half if victim has sanct, to a minimum 1 */ if (AFF_FLAGGED(victim, AFF_SANCTUARY) && dam >= 2) dam /= 2; /* Check for PK if this is not a PK MUD */ if (!pk_allowed) { check_killer(ch, victim); if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim)) dam = 0; } /* Set the maximum damage per round and subtract the hit points */ dam = MAX(MIN(dam, 100), 0); GET_HIT(victim) -= dam; /* Gain exp for the hit */ if (ch != victim) gain_exp(ch, GET_LEVEL(victim) * dam); update_pos(victim); /* * skill_message sends a message from the messages file in lib/misc. * dam_message just sends a generic "You hit $n extremely hard.". * skill_message is preferable to dam_message because it is more * descriptive. * * If we are _not_ attacking with a weapon (i.e. a spell), always use * skill_message. If we are attacking with a weapon: If this is a miss or a * death blow, send a skill_message if one exists; if not, default to a * dam_message. Otherwise, always send a dam_message. */ if (!IS_WEAPON(attacktype)) skill_message(dam, ch, victim, attacktype); else { if (GET_POS(victim) == POS_DEAD || dam == 0) { if (!skill_message(dam, ch, victim, attacktype)) dam_message(dam, ch, victim, attacktype); } else { dam_message(dam, ch, victim, attacktype); } } /* Use send_to_char -- act() doesn't send message if you are DEAD. */ switch (GET_POS(victim)) { case POS_MORTALLYW: act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are mortally wounded, and will die soon, if not aided.\r\n"); break; case POS_INCAP: act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are incapacitated an will slowly die, if not aided.\r\n"); break; case POS_STUNNED: act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You're stunned, but will probably regain consciousness again.\r\n"); break; case POS_DEAD: act("$n is dead! R.I.P.", FALSE, victim, 0, 0, CommTarget::TO_ROOM); send_to_char(victim, "You are dead! Sorry...\r\n"); break; default: /* >= POSITION SLEEPING */ if (dam > (GET_MAX_HIT(victim) / 4)) send_to_char(victim, "That really did HURT!\r\n"); if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 4)) { send_to_char(victim, "%sYou wish that your wounds would stop BLEEDING so much!%s\r\n", CCRED(victim, C_SPR), CCNRM(victim, C_SPR)); if (ch != victim && MOB_FLAGGED(victim, MOB_WIMPY)) do_flee(victim, NULL, 0, 0); } if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) && GET_HIT(victim) < GET_WIMP_LEV(victim) && GET_HIT(victim) > 0) { send_to_char(victim, "You wimp out, and attempt to flee!\r\n"); do_flee(victim, NULL, 0, 0); } break; } /* Help out poor linkless people who are attacked */ if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED) { do_flee(victim, NULL, 0, 0); if (!FIGHTING(victim)) { act("$n is rescued by divine forces.", FALSE, victim, 0, 0, CommTarget::TO_ROOM); GET_WAS_IN(victim) = IN_ROOM(victim); char_from_room(victim); char_to_room(victim, 0); } } /* stop someone from fighting if they're stunned or worse */ if (GET_POS(victim) <= POS_STUNNED && FIGHTING(victim) != NULL) stop_fighting(victim); /* Uh oh. Victim died. */ if (GET_POS(victim) == POS_DEAD) { if (ch != victim && (IS_NPC(victim) || victim->desc)) { if (AFF_FLAGGED(ch, AFF_GROUP)) group_gain(ch, victim); else solo_gain(ch, victim); } if (!IS_NPC(victim)) { mudlog(BRF, LVL_IMMORT, TRUE, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch), world[IN_ROOM(victim)].name); if (MOB_FLAGGED(ch, MOB_MEMORY)) forget(ch, victim); } die(victim); return (-1); } return (dam); }
void autoquest_trigger_check(struct char_data *ch, struct char_data *vict, struct obj_data *object, int type) { struct char_data *i; qst_rnum rnum; int found = TRUE; if (IS_NPC(ch)) return; if (GET_QUEST(ch) == NOTHING) /* No current quest, skip this */ return; if (GET_QUEST_TYPE(ch) != type) return; if ((rnum = real_quest(GET_QUEST(ch))) == NOTHING) return; switch (type) { case AQ_OBJ_FIND: if (QST_TARGET(rnum) == GET_OBJ_VNUM(object)) generic_complete_quest(ch); break; case AQ_ROOM_FIND: if (QST_TARGET(rnum) == world[IN_ROOM(ch)].number) generic_complete_quest(ch); break; case AQ_MOB_FIND: for (i=world[IN_ROOM(ch)].people; i; i = i->next_in_room) if (IS_NPC(i)) if (QST_TARGET(rnum) == GET_MOB_VNUM(i)) generic_complete_quest(ch); break; case AQ_MOB_KILL: if (!IS_NPC(ch) && IS_NPC(vict) && (ch != vict)) if (QST_TARGET(rnum) == GET_MOB_VNUM(vict)) generic_complete_quest(ch); break; case AQ_MOB_SAVE: if (ch == vict) found = FALSE; for (i = world[IN_ROOM(ch)].people; i && found; i = i->next_in_room) if (i && IS_NPC(i) && !MOB_FLAGGED(i, MOB_NOTDEADYET)) if ((GET_MOB_VNUM(i) != QST_TARGET(rnum)) && !AFF_FLAGGED(i, AFF_CHARM)) found = FALSE; if (found) generic_complete_quest(ch); break; case AQ_OBJ_RETURN: if (IS_NPC(vict) && (GET_MOB_VNUM(vict) == QST_RETURNMOB(rnum))) if (object && (GET_OBJ_VNUM(object) == QST_TARGET(rnum))) generic_complete_quest(ch); break; case AQ_ROOM_CLEAR: if (QST_TARGET(rnum) == world[IN_ROOM(ch)].number) { for (i = world[IN_ROOM(ch)].people; i && found; i = i->next_in_room) if (i && IS_NPC(i) && !MOB_FLAGGED(i, MOB_NOTDEADYET)) found = FALSE; if (found) generic_complete_quest(ch); } break; default: log("SYSERR: Invalid quest type passed to autoquest_trigger_check"); break; } }
void mobile_activity(void) { struct char_data *ch, *next_ch, *vict; struct obj_data *obj, *best_obj; int door, found, max; memory_rec *names; for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; if (!IS_MOB(ch)) continue; /* Examine call for special procedure */ if (MOB_FLAGGED(ch, MOB_SPEC) && !no_specials) { if (mob_index[GET_MOB_RNUM(ch)].func == NULL) { log("SYSERR: %s (#%d): Attempting to call non-existing mob function.", GET_NAME(ch), GET_MOB_VNUM(ch)); REMOVE_BIT_AR(MOB_FLAGS(ch), MOB_SPEC); } else { char actbuf[MAX_INPUT_LENGTH] = ""; if ((mob_index[GET_MOB_RNUM(ch)].func) (ch, ch, 0, actbuf)) continue; /* go to next char */ } } /* If the mob has no specproc, do the default actions */ if (FIGHTING(ch) || !AWAKE(ch)) continue; /* hunt a victim, if applicable */ hunt_victim(ch); /* Scavenger (picking up objects) */ if (MOB_FLAGGED(ch, MOB_SCAVENGER)) if (world[IN_ROOM(ch)].contents && !rand_number(0, 10)) { max = 1; best_obj = NULL; for (obj = world[IN_ROOM(ch)].contents; obj; obj = obj->next_content) if (CAN_GET_OBJ(ch, obj) && GET_OBJ_COST(obj) > max) { best_obj = obj; max = GET_OBJ_COST(obj); } if (best_obj != NULL) { obj_from_room(best_obj); obj_to_char(best_obj, ch); act("$n gets $p.", FALSE, ch, best_obj, 0, TO_ROOM); } } /* Mob Movement */ if (!MOB_FLAGGED(ch, MOB_SENTINEL) && (GET_POS(ch) == POS_STANDING) && ((door = rand_number(0, 18)) < DIR_COUNT) && CAN_GO(ch, door) && !ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_NOMOB) && !ROOM_FLAGGED(EXIT(ch, door)->to_room, ROOM_DEATH) && (!MOB_FLAGGED(ch, MOB_STAY_ZONE) || (world[EXIT(ch, door)->to_room].zone == world[IN_ROOM(ch)].zone))) { /* If the mob is charmed, do not move the mob. */ if (ch->master == NULL) perform_move(ch, door, 1); } /* Aggressive Mobs */ if (!MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (IS_NPC(vict) || !CAN_SEE(ch, vict) || PRF_FLAGGED(vict, PRF_NOHASSLE)) continue; if (MOB_FLAGGED(ch, MOB_WIMPY) && AWAKE(vict)) continue; if (MOB_FLAGGED(ch, MOB_AGGRESSIVE ) || (MOB_FLAGGED(ch, MOB_AGGR_EVIL ) && IS_EVIL(vict)) || (MOB_FLAGGED(ch, MOB_AGGR_NEUTRAL) && IS_NEUTRAL(vict)) || (MOB_FLAGGED(ch, MOB_AGGR_GOOD ) && IS_GOOD(vict))) { /* Can a master successfully control the charmed monster? */ if (aggressive_mob_on_a_leash(ch, ch->master, vict)) continue; hit(ch, vict, TYPE_UNDEFINED); found = TRUE; } } } /* Mob Memory */ if (MOB_FLAGGED(ch, MOB_MEMORY) && MEMORY(ch)) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (IS_NPC(vict) || !CAN_SEE(ch, vict) || PRF_FLAGGED(vict, PRF_NOHASSLE)) continue; for (names = MEMORY(ch); names && !found; names = names->next) { if (names->id != GET_IDNUM(vict)) continue; /* Can a master successfully control the charmed monster? */ if (aggressive_mob_on_a_leash(ch, ch->master, vict)) continue; found = TRUE; act("'Hey! You're the fiend that attacked me!!!', exclaims $n.", FALSE, ch, 0, 0, TO_ROOM); hit(ch, vict, TYPE_UNDEFINED); } } } /* Charmed Mob Rebellion: In order to rebel, there need to be more charmed * monsters than the person can feasibly control at a time. Then the * mobiles have a chance based on the charisma of their leader. * 1-4 = 0, 5-7 = 1, 8-10 = 2, 11-13 = 3, 14-16 = 4, 17-19 = 5, etc. */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && num_followers_charmed(ch->master) > (GET_CHA(ch->master) - 2) / 3) { if (!aggressive_mob_on_a_leash(ch, ch->master, ch->master)) { if (CAN_SEE(ch, ch->master) && !PRF_FLAGGED(ch->master, PRF_NOHASSLE)) hit(ch, ch->master, TYPE_UNDEFINED); stop_follower(ch); } } /* Helper Mobs */ if (MOB_FLAGGED(ch, MOB_HELPER) && (!AFF_FLAGGED(ch, AFF_BLIND) || !AFF_FLAGGED(ch, AFF_CHARM))) { found = FALSE; for (vict = world[IN_ROOM(ch)].people; vict && !found; vict = vict->next_in_room) { if (ch == vict || !IS_NPC(vict) || !FIGHTING(vict)) continue; if (IS_NPC(FIGHTING(vict)) || ch == FIGHTING(vict)) continue; act("$n jumps to the aid of $N!", FALSE, ch, 0, vict, TO_ROOM); hit(ch, FIGHTING(vict), TYPE_UNDEFINED); found = TRUE; } } /* Add new mobile actions here */ } /* end for() */ }
int cast_spell(struct char_data *ch, struct char_data *tch, struct obj_data *tobj, struct spell_info_type *sptr, char *tar_str) { if (!magic_enabled) return (0); if (!sptr) { extended_mudlog(NRM, SYSL_BUGS, TRUE, "cast_spell() called without a valid sptr: ch: %s, tch: %s", GET_NAME(ch), GET_NAME(tch)); return (0); } if (GET_POS(ch) < sptr->min_position) { switch (GET_POS(ch)) { case POS_SLEEPING: send_to_char("You dream about great magical powers.\r\n", ch); break; case POS_RESTING: send_to_char("You cannot concentrate while resting.\r\n", ch); break; case POS_SITTING: send_to_char("You can't do this sitting!\r\n", ch); break; case POS_FIGHTING: send_to_char("Impossible! You can't concentrate enough!\r\n", ch); break; default: send_to_char("You can't do much of anything like this!\r\n", ch); break; } return (0); } if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == tch)) { send_to_char("You are afraid you might hurt your master!\r\n", ch); return (0); } if ((tch != ch) && IS_SET(sptr->targets, TAR_SELF_ONLY)) { send_to_char("You can only cast this spell upon yourself!\r\n", ch); return (0); } if ((tch == ch) && IS_SET(sptr->targets, TAR_NOT_SELF)) { send_to_char("You cannot cast this spell upon yourself!\r\n", ch); return (0); } if (IS_SET(sptr->routines, MAG_GROUPS) && !AFF_FLAGGED(ch, AFF_GROUP)) { send_to_char("You can't cast this spell if you're not in a group!\r\n",ch); return (0); } if (cast_mtrigger(tch, ch, tar_str, sptr) == 0) return (0); if (cast_otrigger(tobj, ch, tar_str, sptr) == 0) return (0); if (cast_wtrigger(ch, tch, tobj, tar_str, sptr) == 0) return (0); send_to_char(OK, ch); say_spell(ch, sptr, tch, tobj); return (call_magic(ch, tch, tobj, sptr, (GET_SKILL(ch, sptr->skill)/100), CAST_SPELL, tar_str)); }
void beat_points_update(int pulse) { CHAR_DATA *i, *next_char; int restore; if (!UPDATE_PC_ON_BEAT) return; // only for PC's for (i = character_list; i; i = next_char) { next_char = i->next; if (IS_NPC(i)) continue; if (IN_ROOM(i) == NOWHERE) { log("SYSERR: Pulse character in NOWHERE."); continue; } if (RENTABLE(i) <= time(NULL)) { RENTABLE(i) = 0; AGRESSOR(i) = 0; AGRO(i) = 0; i->agrobd = false; } if (AGRO(i) < time(NULL)) AGRO(i) = 0; beat_punish(i); // This line is used only to control all situations when someone is // dead (POS_DEAD). You can comment it to minimize heartbeat function // working time, if you're sure, that you control these situations // everywhere. To the time of this code revision I've fix some of them // and haven't seen any other. // if (GET_POS(i) == POS_DEAD) // die(i, NULL); if (GET_POS(i) < POS_STUNNED) continue; // Restore hitpoints restore = hit_gain(i); restore = interpolate(restore, pulse); if (AFF_FLAGGED(i, AFF_BANDAGE)) { AFFECT_DATA* aff; for(aff = i->affected; aff; aff = aff->next) { if (aff->type == SPELL_BANDAGE) { restore += MIN(GET_REAL_MAX_HIT(i) / 10, aff->modifier); break; } } } if (GET_HIT(i) < GET_REAL_MAX_HIT(i)) GET_HIT(i) = MIN(GET_HIT(i) + restore, GET_REAL_MAX_HIT(i)); // Проверка аффекта !исступление!. Поместил именно здесь, // но если кто найдет более подходящее место переносите =) //Gorrah: перенес в handler::affect_total //check_berserk(i); // Restore PC caster mem if (!IS_MANA_CASTER(i) && !MEMQUEUE_EMPTY(i)) { restore = mana_gain(i); restore = interpolate(restore, pulse); GET_MEM_COMPLETED(i) += restore; if (AFF_FLAGGED(i, AFF_RECALL_SPELLS)) handle_recall_spells(i); while (GET_MEM_COMPLETED(i) > GET_MEM_CURRENT(i) && !MEMQUEUE_EMPTY(i)) { int spellnum; spellnum = MemQ_learn(i); GET_SPELL_MEM(i, spellnum)++; GET_CASTER(i) += spell_info[spellnum].danger; } if (MEMQUEUE_EMPTY(i)) { if (GET_RELIGION(i) == RELIGION_MONO) { send_to_char ("Наконец ваши занятия окончены. Вы с улыбкой захлопнули свой часослов.\r\n", i); act("Окончив занятия, $n с улыбкой захлопнул$g часослов.", FALSE, i, 0, 0, TO_ROOM); } else { send_to_char ("Наконец ваши занятия окончены. Вы с улыбкой убрали свои резы.\r\n", i); act("Окончив занятия, $n с улыбкой убрал$g резы.", FALSE, i, 0, 0, TO_ROOM); } } } if (!IS_MANA_CASTER(i) && MEMQUEUE_EMPTY(i)) { GET_MEM_TOTAL(i) = 0; GET_MEM_COMPLETED(i) = 0; } // Гейн маны у волхвов if (IS_MANA_CASTER(i) && GET_MANA_STORED(i) < GET_MAX_MANA(i)) { GET_MANA_STORED(i) += mana_gain(i); if (GET_MANA_STORED(i) >= GET_MAX_MANA(i)) { GET_MANA_STORED(i) = GET_MAX_MANA(i); send_to_char("Ваша магическая энергия полностью восстановилась\r\n", i); } } if (IS_MANA_CASTER(i) && GET_MANA_STORED(i) > GET_MAX_MANA(i)) { GET_MANA_STORED(i) = GET_MAX_MANA(i); } // Restore moves restore = move_gain(i); restore = interpolate(restore, pulse); // GET_MOVE(i) = MIN(GET_MOVE(i) + restore, GET_REAL_MAX_MOVE(i)); //MZ.overflow_fix if (GET_MOVE(i) < GET_REAL_MAX_MOVE(i)) GET_MOVE(i) = MIN(GET_MOVE(i) + restore, GET_REAL_MAX_MOVE(i)); //-MZ.overflow_fix } }
// 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); }
/** Move a PC/NPC character from their current location to a new location. This * is the standard movement locomotion function that all normal walking * movement by characters should be sent through. This function also defines * the move cost of normal locomotion as: * ( (move cost for source room) + (move cost for destination) ) / 2 * * @pre Function assumes that ch has no master controlling character, that * ch has no followers (in other words followers won't be moved by this * function) and that the direction traveled in is one of the valid, enumerated * direction. * @param ch The character structure to attempt to move. * @param dir The defined direction (NORTH, SOUTH, etc...) to attempt to * move into. * @param need_specials_check If TRUE will cause * @retval int 1 for a successful move (ch is now in a new location) * or 0 for a failed move (ch is still in the original location). */ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) { /* Begin Local variable definitions */ /*---------------------------------------------------------------------*/ /* Used in our special proc check. By default, we pass a NULL argument * when checking for specials */ char spec_proc_args[MAX_INPUT_LENGTH] = ""; /* The room the character is currently in and will move from... */ room_rnum was_in = IN_ROOM(ch); /* ... and the room the character will move into. */ room_rnum going_to = EXIT(ch, dir)->to_room; /* How many movement points are required to travel from was_in to going_to. * We redefine this later when we need it. */ int need_movement = 0; /* Contains the "leave" message to display to the was_in room. */ char leave_message[SMALL_BUFSIZE]; /*---------------------------------------------------------------------*/ /* End Local variable definitions */ /* Begin checks that can prevent a character from leaving the was_in room. */ /* Future checks should be implemented within this section and return 0. */ /*---------------------------------------------------------------------*/ /* Check for special routines that might activate because of the move and * also might prevent the movement. Special requires commands, so we pass * in the "command" equivalent of the direction (ie. North is '1' in the * command list, but NORTH is defined as '0'). * Note -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, spec_proc_args)) return 0; /* Leave Trigger Checks: Does a leave trigger block exit from the room? */ if (!leave_mtrigger(ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; if (!leave_otrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; /* Charm effect: Does it override the movement? */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && was_in == IN_ROOM(ch->master)) { send_to_char(ch, "The thought of leaving your master makes you weep.\r\n"); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); return (0); } /* Water, No Swimming Rooms: Does the deep water prevent movement? */ if ((SECT(was_in) == SECT_WATER_NOSWIM) || (SECT(going_to) == SECT_WATER_NOSWIM)) { if (!has_boat(ch)) { send_to_char(ch, "You need a boat to go there.\r\n"); return (0); } } /* Flying Required: Does lack of flying prevent movement? */ if ((SECT(was_in) == SECT_FLYING) || (SECT(going_to) == SECT_FLYING)) { if (!has_flight(ch)) { send_to_char(ch, "You need to be flying to go there!\r\n"); return (0); } } /* Underwater Room: Does lack of underwater breathing prevent movement? */ if ((SECT(was_in) == SECT_UNDERWATER) || (SECT(going_to) == SECT_UNDERWATER)) { if (!has_scuba(ch) && !IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_NOHASSLE)) { send_to_char(ch, "You need to be able to breathe water to go there!\r\n"); return (0); } } /* Houses: Can the player walk into the house? */ if (ROOM_FLAGGED(was_in, ROOM_ATRIUM)) { if (!House_can_enter(ch, GET_ROOM_VNUM(going_to))) { send_to_char(ch, "That's private property -- no trespassing!\r\n"); return (0); } } /* Check zone level recommendations */ if ((ZONE_MINLVL(GET_ROOM_ZONE(going_to)) != -1) && ZONE_MINLVL(GET_ROOM_ZONE(going_to)) > GET_LEVEL(ch)) { send_to_char(ch, "This zone is above your recommended level.\r\n"); } /* Check zone flag restrictions */ if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_CLOSED)) { send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n"); return (0); } if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_NOIMMORT) && (GET_ADMLEVEL(ch) >= ADMLVL_IMMORT) && (GET_ADMLEVEL(ch) < ADMLVL_GRGOD)) { send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n"); return (0); } /* Room Size Capacity: Is the room full of people already? */ if (ROOM_FLAGGED(going_to, ROOM_TUNNEL) && num_pc_in_room(&(world[going_to])) >= CONFIG_TUNNEL_SIZE) { if (CONFIG_TUNNEL_SIZE > 1) send_to_char(ch, "There isn't enough room for you to go there!\r\n"); else send_to_char(ch, "There isn't enough room there for more than one person!\r\n"); return (0); } /* Room Level Requirements: Is ch privileged enough to enter the room? */ if (ROOM_FLAGGED(going_to, ROOM_GODROOM) && GET_ADMLEVEL(ch) < ADMLVL_GOD) { send_to_char(ch, "You aren't godly enough to use that room!\r\n"); return (0); } /* All checks passed, nothing will prevent movement now other than lack of * move points. */ /* move points needed is avg. move loss for src and destination sect type */ need_movement = (movement_loss[SECT(was_in)] + movement_loss[SECT(going_to)]) / 2; /* Move Point Requirement Check */ if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { if (need_specials_check && ch->master) send_to_char(ch, "You are too exhausted to follow.\r\n"); else send_to_char(ch, "You are too exhausted.\r\n"); return (0); } /*---------------------------------------------------------------------*/ /* End checks that can prevent a character from leaving the was_in room. */ /* Begin: the leave operation. */ /*---------------------------------------------------------------------*/ /* If applicable, subtract movement cost. */ if (GET_ADMLEVEL(ch) < ADMLVL_IMMORT && !IS_NPC(ch)) GET_MOVE(ch) -= need_movement; /* Generate the leave message and display to others in the was_in room. */ if (!AFF_FLAGGED(ch, AFF_SNEAK)) { snprintf(leave_message, sizeof(leave_message), "$n leaves %s.", dirs[dir]); act(leave_message, TRUE, ch, 0, 0, TO_ROOM); } char_from_room(ch); char_to_room(ch, going_to); /*---------------------------------------------------------------------*/ /* End: the leave operation. The character is now in the new room. */ /* Begin: Post-move operations. */ /*---------------------------------------------------------------------*/ /* Post Move Trigger Checks: Check the new room for triggers. * Assumptions: The character has already truly left the was_in room. If * the entry trigger "prevents" movement into the room, it is the triggers * job to provide a message to the original was_in room. */ if (!entry_mtrigger(ch) || !enter_wtrigger(&world[going_to], ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); return 0; } /* Display arrival information to anyone in the destination room... */ if (!AFF_FLAGGED(ch, AFF_SNEAK)) act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM); /* ... and the room description to the character. */ if (ch->desc != NULL) look_at_room(ch, 0); /* ... and Kill the player if the room is a death trap. */ if (ROOM_FLAGGED(going_to, ROOM_DEATH) && GET_ADMLEVEL(ch) < ADMLVL_IMMORT) { mudlog(BRF, ADMLVL_IMMORT, TRUE, "%s hit death trap #%d (%s)", GET_NAME(ch), GET_ROOM_VNUM(going_to), world[going_to].name); death_cry(ch); extract_char(ch); return (0); } /* At this point, the character is safe and in the room. */ /* Fire memory and greet triggers, check and see if the greet trigger * prevents movement, and if so, move the player back to the previous room. */ entry_memory_mtrigger(ch); if (!greet_mtrigger(ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); look_at_room(ch, 0); /* Failed move, return a failure */ return (0); } else greet_memory_mtrigger(ch); /*---------------------------------------------------------------------*/ /* End: Post-move operations. */ /* Only here is the move successful *and* complete. Return success for * calling functions to handle post move operations. */ return (1); }
/* do_simple_move assumes * 1. That there is no master and no followers. * 2. That the direction exists. * * Returns : * 1 : If succes. * 0 : If fail */ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) { char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */ room_rnum was_in; int need_movement, moveadd = 0; struct obj_data *k; /* * Check for special routines (North is 1 in command list, but 0 here) Note * -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, throwaway)) return (0); /* blocked by a leave trigger ? */ if (!leave_mtrigger(ch, dir)) return 0; if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir)) return 0; /* charmed? */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) { send_to_char(ch, "The thought of leaving your master makes you weep.\r\n"); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); return (0); } /* if this room or the one we're going to needs a boat, check for one */ if ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) || (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) { if (!has_boat(ch)) { send_to_char(ch, "You need a boat to go there.\r\n"); return (0); } } /* move points needed is avg. move loss for src and destination sect type * You know .. I don't like this system, let's base this not ONLY on terrain type * but also on dex of char. * Needs to adjust on max abils * Original: * need_movement = (movement_loss[SECT(IN_ROOM(ch))] + movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2; */ if (GET_DEX(ch) <= 5) /* 0(1?)-5 Dex */ moveadd = 8; if ((GET_DEX(ch) >= 6) && (GET_DEX(ch) <= 10)) /* 6-10 Dex */ moveadd = 6; if ((GET_DEX(ch) >= 11) && (GET_DEX(ch) <= 15)) /* 11-15 Dex */ moveadd = 4; if (GET_DEX(ch) >= 16) /* 16+ Up to ..? Dex */ moveadd = 2; need_movement = (movement_loss[SECT(IN_ROOM(ch))] + movement_loss[SECT(EXIT(ch, dir)->to_room)] + moveadd) / 2; if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { if (need_specials_check && ch->master) send_to_char(ch, "You are too exhausted to follow.\r\n"); else send_to_char(ch, "You are too exhausted.\r\n"); return (0); } if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) { if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) { send_to_char(ch, "That's private property -- no trespassing!\r\n"); return (0); } } if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) && num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= tunnel_size) { if (tunnel_size > 1) send_to_char(ch, "There isn't enough room for you to go there!\r\n"); else send_to_char(ch, "There isn't enough room there for more than one person!\r\n"); return (0); } /* Room big enough for you? */ if ((SIZE(EXIT(ch, dir)->to_room) < GET_SIZE(ch)) && (SIZE(EXIT(ch, dir)->to_room) != SIZE_SPECIAL) && (GET_LEVEL(ch) < LVL_GOD)) { //GOD+ can enter any room send_to_char(ch, "You are too big to fit in there!\r\n"); return (0); } /* Mortals and low level gods cannot enter greater god rooms. */ /* irrelevant because of min/max level -mak 8.21.05 -reinstated 2.9.06 if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GOD) { send_to_char(ch, "You aren't godly enough to use that room!\r\n"); return (0); } uncomment to fix GODROOM */ /* No access for non-IMPs */ if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_IMPROOM) && GET_LEVEL(ch) < LVL_IMPL) { send_to_char(ch, "You dare not disturb the Implementors!\r\n"); return (0); } if (GET_LEVEL(ch) < ROOM_MIN_LEVEL(EXIT(ch, dir)->to_room)) { if (world[EXIT(ch, dir)->to_room].max_level_message ) { send_to_char(ch, world[EXIT(ch, dir)->to_room].min_level_message); send_to_char(ch, "\r\n"); } else send_to_char(ch, "You are not experienced enough to enter that room.\r\n"); return 0; } if (ROOM_MAX_LEVEL(EXIT(ch, dir)->to_room) > 0) { if (GET_LEVEL(ch) > ROOM_MAX_LEVEL(EXIT(ch, dir)->to_room) && GET_LEVEL(ch) < LVL_SAINT ) { if (world[EXIT(ch, dir)->to_room].max_level_message ){ send_to_char(ch, world[EXIT(ch, dir)->to_room].max_level_message); send_to_char(ch, "\r\n"); } else send_to_char(ch, "You are too experienced to enter that room.\r\n"); return 0; } } if (AFF_FLAGGED(ch, AFF_FLEET_FEET)) { need_movement = need_movement / 2; if (need_movement < 2) need_movement = 1;} if (AFF_FLAGGED(ch, AFF_AIRWALK)) need_movement = 1; /* Now we know we're allowed to go into the room. */ if (GET_LEVEL(ch) < LVL_SAINT && !IS_NPC(ch)) GET_MOVE(ch) -= need_movement; if (!AFF_FLAGGED(ch, AFF_SNEAK)) { char buf2[MAX_STRING_LENGTH]; snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]); act(buf2, TRUE, ch, 0, 0, TO_ROOM); } was_in = IN_ROOM(ch); char_from_room(ch); char_to_room(ch, world[was_in].dir_option[dir]->to_room); /* move them first, then move them back if they aren't allowed to go. */ /* see if an entry trigger disallows the move */ if (!entry_mtrigger(ch) || !enter_wtrigger(&world[IN_ROOM(ch)], ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); return 0; } if (!AFF_FLAGGED(ch, AFF_SNEAK)) act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM); if (ch->desc != NULL) look_at_room(IN_ROOM(ch), ch, 0); if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_SAINT) { clanlog(ch, "%s entered a Death Room", GET_NAME(ch)); was_in = IN_ROOM(ch); log_death_trap(ch); death_cry(ch); /* Fix the PCs size first if it needs fixing */ fix_size(ch); extract_char(ch); for (k = world[was_in].contents; k; k = world[was_in].contents) extract_obj(k); return (0); } entry_memory_mtrigger(ch); if (!greet_mtrigger(ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); look_at_room(IN_ROOM(ch), ch, 0); } else greet_memory_mtrigger(ch); /* send warning message if moves are getting low */ if ( GET_MOVE(ch) < (GET_MAX_MOVE(ch) / 10) ) { send_to_char(ch, "You cannot go much further.\r\n"); } return (1); }
// Returns true if the player can see at all, regardless of other influences bool check_sight_self(struct creature * self) { return !AFF_FLAGGED(self, AFF_BLIND) || AFF3_FLAGGED(self, AFF3_SONIC_IMAGERY); }
/* do_simple_move assumes that there is no master, no followers and that the * direction exists. It returns 1 for success, 0 if failure. */ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) { char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */ room_rnum was_in = IN_ROOM(ch); int need_movement; /* Check for special routines (North is 1 in command list, but 0 here) Note * -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, throwaway)) return (0); /* blocked by a leave trigger ? */ if (!leave_mtrigger(ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; if (!leave_otrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */ return 0; /* charmed? */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) { send_to_char(ch, "The thought of leaving your master makes you weep.\r\n"); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); return (0); } /* if this room or the one we're going to needs a boat, check for one */ if ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) || (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) { if (!has_boat(ch)) { send_to_char(ch, "You need a boat to go there.\r\n"); return (0); } } /* If this room or the one we're going to needs flight, check for it. */ if ((SECT(IN_ROOM(ch)) == SECT_FLYING) || (SECT(EXIT(ch, dir)->to_room) == SECT_FLYING)) { if (!has_flight(ch)) { send_to_char(ch, "You need to be flying to go there!\r\n"); return (0); } } /* If this room or the one we're going to needs scuba, check for it. */ if ((SECT(IN_ROOM(ch)) == SECT_UNDERWATER) || (SECT(EXIT(ch, dir)->to_room) == SECT_UNDERWATER)) { if (!has_scuba(ch)) { send_to_char(ch, "You need to be able to breathe water to go there!\r\n"); return (0); } } /* move points needed is avg. move loss for src and destination sect type */ need_movement = (movement_loss[SECT(IN_ROOM(ch))] + movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2; if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) { if (need_specials_check && ch->master) send_to_char(ch, "You are too exhausted to follow.\r\n"); else send_to_char(ch, "You are too exhausted.\r\n"); return (0); } if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) { if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) { send_to_char(ch, "That's private property -- no trespassing!\r\n"); return (0); } } if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) && num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= CONFIG_TUNNEL_SIZE) { if (CONFIG_TUNNEL_SIZE > 1) send_to_char(ch, "There isn't enough room for you to go there!\r\n"); else send_to_char(ch, "There isn't enough room there for more than one person!\r\n"); return (0); } /* Mortals and low level gods cannot enter greater god rooms. */ if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GOD) { send_to_char(ch, "You aren't godly enough to use that room!\r\n"); return (0); } /* Now we know we're allowed to go into the room. */ if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch)) GET_MOVE(ch) -= need_movement; if (!AFF_FLAGGED(ch, AFF_SNEAK)) { char buf2[MAX_STRING_LENGTH]; snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]); act(buf2, TRUE, ch, 0, 0, TO_ROOM); } was_in = IN_ROOM(ch); char_from_room(ch); char_to_room(ch, world[was_in].dir_option[dir]->to_room); /* move them first, then move them back if they aren't allowed to go. Also, * see if an entry trigger disallows the move */ if (!entry_mtrigger(ch) || !enter_wtrigger(&world[IN_ROOM(ch)], ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); return 0; } if (!AFF_FLAGGED(ch, AFF_SNEAK)) act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM); if (ch->desc != NULL) look_at_room(ch, 0); if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) { mudlog(BRF, LVL_IMMORT, TRUE, "%s hit death trap #%d (%s)", GET_NAME(ch), GET_ROOM_VNUM(IN_ROOM(ch)), world[IN_ROOM(ch)].name); death_cry(ch); extract_char(ch); return (0); } entry_memory_mtrigger(ch); if (!greet_mtrigger(ch, dir)) { char_from_room(ch); char_to_room(ch, was_in); look_at_room(ch, 0); } else greet_memory_mtrigger(ch); return (1); }
/* 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 }
void mag_affects(int level, struct char_data *ch, struct char_data *victim, int spellnum, int savetype) { struct affected_type af[MAX_SPELL_AFFECTS]; bool accum_affect = FALSE, accum_duration = FALSE; const char *to_vict = NULL, *to_room = NULL; int i; if (victim == NULL || ch == NULL) return; for (i = 0; i < MAX_SPELL_AFFECTS; i++) { af[i].type = spellnum; af[i].bitvector = 0; af[i].modifier = 0; af[i].location = APPLY_NONE; } switch (spellnum) { case SPELL_CHILL_TOUCH: af[0].location = APPLY_STR; if (mag_savingthrow(victim, savetype, 0)) af[0].duration = 1; else af[0].duration = 4; af[0].modifier = -1; accum_duration = TRUE; to_vict = "You feel your strength wither!"; break; case SPELL_ARMOR: af[0].location = APPLY_AC; af[0].modifier = -20; af[0].duration = 24; accum_duration = TRUE; to_vict = "You feel someone protecting you."; break; case SPELL_BLESS: af[0].location = APPLY_HITROLL; af[0].modifier = 2; af[0].duration = 6; af[1].location = APPLY_SAVING_SPELL; af[1].modifier = -1; af[1].duration = 6; accum_duration = TRUE; to_vict = "You feel righteous."; break; case SPELL_BLINDNESS: if (MOB_FLAGGED(victim,MOB_NOBLIND) || mag_savingthrow(victim, savetype, 0)) { send_to_char(ch, "You fail.\r\n"); return; } af[0].location = APPLY_HITROLL; af[0].modifier = -4; af[0].duration = 2; af[0].bitvector = AFF_BLIND; af[1].location = APPLY_AC; af[1].modifier = 40; af[1].duration = 2; af[1].bitvector = AFF_BLIND; to_room = "$n seems to be blinded!"; to_vict = "You have been blinded!"; break; case SPELL_CURSE: if (mag_savingthrow(victim, savetype, 0)) { send_to_char(ch, "%s", NOEFFECT); return; } af[0].location = APPLY_HITROLL; af[0].duration = 1 + (GET_LEVEL(ch) / 2); af[0].modifier = -1; af[0].bitvector = AFF_CURSE; af[1].location = APPLY_DAMROLL; af[1].duration = 1 + (GET_LEVEL(ch) / 2); af[1].modifier = -1; af[1].bitvector = AFF_CURSE; accum_duration = TRUE; accum_affect = TRUE; to_room = "$n briefly glows red!"; to_vict = "You feel very uncomfortable."; break; case SPELL_DETECT_ALIGN: af[0].duration = 12 + level; af[0].bitvector = AFF_DETECT_ALIGN; accum_duration = TRUE; to_vict = "Your eyes tingle."; break; case SPELL_DETECT_INVIS: af[0].duration = 12 + level; af[0].bitvector = AFF_DETECT_INVIS; accum_duration = TRUE; to_vict = "Your eyes tingle."; break; case SPELL_DETECT_MAGIC: af[0].duration = 12 + level; af[0].bitvector = AFF_DETECT_MAGIC; accum_duration = TRUE; to_vict = "Your eyes tingle."; break; case SPELL_INFRAVISION: af[0].duration = 12 + level; af[0].bitvector = AFF_INFRAVISION; accum_duration = TRUE; to_vict = "Your eyes glow red."; to_room = "$n's eyes glow red."; break; case SPELL_INVISIBLE: if (!victim) victim = ch; af[0].duration = 12 + (GET_LEVEL(ch) / 4); af[0].modifier = -40; af[0].location = APPLY_AC; af[0].bitvector = AFF_INVISIBLE; accum_duration = TRUE; to_vict = "You vanish."; to_room = "$n slowly fades out of existence."; break; case SPELL_POISON: if (mag_savingthrow(victim, savetype, 0)) { send_to_char(ch, "%s", NOEFFECT); return; } af[0].location = APPLY_STR; af[0].duration = GET_LEVEL(ch); af[0].modifier = -2; af[0].bitvector = AFF_POISON; to_vict = "You feel very sick."; to_room = "$n gets violently ill!"; break; case SPELL_PROT_FROM_EVIL: af[0].duration = 24; af[0].bitvector = AFF_PROTECT_EVIL; accum_duration = TRUE; to_vict = "You feel invulnerable!"; break; case SPELL_SANCTUARY: af[0].duration = 4; af[0].bitvector = AFF_SANCTUARY; accum_duration = TRUE; to_vict = "A white aura momentarily surrounds you."; to_room = "$n is surrounded by a white aura."; break; case SPELL_SLEEP: if (!pk_allowed && !IS_NPC(ch) && !IS_NPC(victim)) return; if (MOB_FLAGGED(victim, MOB_NOSLEEP)) return; if (mag_savingthrow(victim, savetype, 0)) return; af[0].duration = 4 + (GET_LEVEL(ch) / 4); af[0].bitvector = AFF_SLEEP; if (GET_POS(victim) > POS_SLEEPING) { send_to_char(victim, "You feel very sleepy... Zzzz......\r\n"); act("$n goes to sleep.", TRUE, victim, 0, 0, TO_ROOM); GET_POS(victim) = POS_SLEEPING; } break; case SPELL_STRENGTH: if (GET_ADD(victim) == 100) return; af[0].location = APPLY_STR; af[0].duration = (GET_LEVEL(ch) / 2) + 4; af[0].modifier = 1 + (level > 18); accum_duration = TRUE; accum_affect = TRUE; to_vict = "You feel stronger!"; break; case SPELL_SENSE_LIFE: to_vict = "Your feel your awareness improve."; af[0].duration = GET_LEVEL(ch); af[0].bitvector = AFF_SENSE_LIFE; accum_duration = TRUE; break; case SPELL_WATERWALK: af[0].duration = 24; af[0].bitvector = AFF_WATERWALK; accum_duration = TRUE; to_vict = "You feel webbing between your toes."; break; } /* * If this is a mob that has this affect set in its mob file, do not * perform the affect. This prevents people from un-sancting mobs * by sancting them and waiting for it to fade, for example. */ if (IS_NPC(victim) && !affected_by_spell(victim, spellnum)) for (i = 0; i < MAX_SPELL_AFFECTS; i++) if (AFF_FLAGGED(victim, af[i].bitvector)) { send_to_char(ch, "%s", NOEFFECT); return; } /* * If the victim is already affected by this spell, and the spell does * not have an accumulative effect, then fail the spell. */ if (affected_by_spell(victim,spellnum) && !(accum_duration||accum_affect)) { send_to_char(ch, "%s", NOEFFECT); return; } for (i = 0; i < MAX_SPELL_AFFECTS; i++) if (af[i].bitvector || (af[i].location != APPLY_NONE)) affect_join(victim, af+i, accum_duration, FALSE, accum_affect, FALSE); if (to_vict != NULL) act(to_vict, FALSE, victim, 0, ch, TO_CHAR); if (to_room != NULL) act(to_room, TRUE, victim, 0, ch, TO_ROOM); }
void mage_best_attack(struct creature *ch, struct creature *vict) { int calculate_mob_aggression(struct creature *, struct creature *); int aggression = calculate_mob_aggression(ch, vict); if (aggression > 75) { // extremely aggressive - just attack hard if (mage_damaging_attack(ch, vict)) return; } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_WORD_STUN)) { cast_spell(ch, vict, NULL, NULL, SPELL_WORD_STUN); return; } else if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_SLEEP)) { cast_spell(ch, vict, NULL, NULL, SPELL_SLEEP); return; } else if (!AFF_FLAGGED(vict, AFF_BLIND) && can_cast_spell(ch, SPELL_BLINDNESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_BLINDNESS); return; } else if (!AFF_FLAGGED(vict, AFF_CURSE) && can_cast_spell(ch, SPELL_CURSE)) { cast_spell(ch, vict, NULL, NULL, SPELL_CURSE); return; } } if (aggression > 25) { // not very aggressive - play more defensively if (can_cast_spell(ch, SPELL_DISPEL_MAGIC) && dispel_is_advisable(vict)) { cast_spell(ch, vict, NULL, NULL, SPELL_DISPEL_MAGIC); return; } else if (!AFF2_FLAGGED(vict, AFF2_SLOW) && can_cast_spell(ch, SPELL_SLOW)) { cast_spell(ch, vict, NULL, NULL, SPELL_SLOW); return; } else if (mage_damaging_attack(ch, vict)) return; } if (aggression > 5) { if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_TELEPORT); return; } else if (can_cast_spell(ch, SPELL_LOCAL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_LOCAL_TELEPORT); return; } } // desperation - just attack full force, as hard as possible if (mage_damaging_attack(ch, vict)) return; else if (can_cast_spell(ch, SKILL_PUNCH)) perform_offensive_skill(ch, vict, SKILL_PUNCH); else hit(ch, vict, TYPE_UNDEFINED); }
/* do_simple_move assumes * 1. That there is no master and no followers. * 2. That the direction exists. * * Returns : * 1 : If succes. * 0 : If fail */ int do_simple_move(struct char_data *ch, int dir, int need_specials_check) { room_rnum was_in; struct char_data *i; /* * Check for special routines (North is 1 in command list, but 0 here) Note * -- only check if following; this avoids 'double spec-proc' bug */ if (need_specials_check && special(ch, dir + 1, "")) { return (0); } /* charmed? */ if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && ch->in_room == ch->master->in_room) { send_to_char("The thought of leaving your master makes you weep.\r\n", ch); act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM); return (0); } /* if this room or the one we're going to needs a boat, check for one */ if ((SECT(ch->in_room) == SECT_WATER_NOSWIM) || (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) { if (!has_boat(ch)) { send_to_char("You need a boat to go there.\r\n", ch); return (0); } } if((IS_CARRYING_W(ch) > (CAN_CARRY_W(ch) * 2) && GET_LEVEL(ch) < LVL_GOD && !IS_NPC(ch))) { send_to_char("You are to heavy to move! Drop something!\r\n", ch); return (0); } if(IS_NPC_FISH(ch)) { if(SECT(EXIT(ch, dir)->to_room) != SECT_BRIDGE && SECT(EXIT(ch, dir)->to_room) != SECT_WATER_SWIM && SECT(EXIT(ch, dir)->to_room) != SECT_WATER_NOSWIM) { // sprintf(buf, "%s %d", dirs[dir], SECT(EXIT(ch, dir)->to_room)); // mobsay(ch, buf); return FALSE; } if(GET_MOB_VNUM(ch) < 1500 && ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_SALT_FISH)) { return FALSE; } } if (SECT(EXIT(ch, dir)->to_room) != SECT_FOREST) { if (IS_NPC_WOLF(ch) || IS_NPC_CRAB(ch) || IS_NPC_SKELETON(ch)) { return (0); } } /* move points needed is avg. move loss for src and destination sect type */ if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) && num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) > 1) { send_to_char("There isn't enough room there for more than one person!\r\n", ch); return (0); } /* Mortals and low level gods cannot enter greater god rooms. */ if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) && GET_LEVEL(ch) < LVL_GRGOD) { send_to_char("You aren't godly enough to use that room!\r\n", ch); return (0); } /* Now we know we're allow to go into the room. */ if(AFF_FLAGGED(ch, AFF_FISHING) || GET_FISHON(ch)) { REMOVE_BIT(AFF_FLAGS(ch), AFF_FISHING); GET_FISHON(ch) = 0; GET_REELIN(ch) = 0; send_to_char("You stop fishing.\r\n", ch); act("$n stops fishing.", FALSE, ch, 0, 0, TO_ROOM); } if (!AFF_FLAGGED(ch, AFF_SNEAK) && !AFF_FLAGGED(ch, AFF_INVISIBLE)) { if(IS_NPC(ch)) { switch(GET_RACE(ch)) { case RACE_NPC_MAMMAL: case RACE_NPC_HIGHHUMAN: case RACE_NPC_GOBLIN: case RACE_NPC_PIG: case RACE_NPC_WOLF: case RACE_NPC_CHICKEN: sprintf(buf2, "$n walks %s.", dirs[dir]); break; case RACE_NPC_AVIAN: sprintf(buf2, "$n flits %s.", dirs[dir]); break; case RACE_NPC_SHEEP: case RACE_NPC_GOAT: sprintf(buf2, "$n walks %s.", dirs[dir]); break; case RACE_NPC_SKELETON: sprintf(buf2, "$n shambles %s.", dirs[dir]); break; case RACE_NPC_COW: sprintf(buf2, "$n walks %s.", dirs[dir]); break; case RACE_NPC_CRAB: sprintf(buf2, "$n scurries %s.", dirs[dir]); break; case RACE_NPC_FISH: sprintf(buf2, "$n swims %s.", dirs[dir]); break; case RACE_NPC_INSECT: sprintf(buf2, "$n buzzes %s.", dirs[dir]); break; default: sprintf(buf2, "$n leaves %s.", dirs[dir]); break; } } else { sprintf(buf2, "$n leaves %s.", dirs[dir]); } if(SECT(ch->in_room) == SECT_WATER_SWIM && !IS_NPC_FISH(ch)) { sprintf(buf2, "$n splashes through the water, heading %s.", dirs[dir]); } act(buf2, FALSE, ch, 0, 0, TO_ROOM); } was_in = ch->in_room; char_from_room(ch); char_to_room(ch, world[was_in].dir_option[dir]->to_room); if (!AFF_FLAGGED(ch, AFF_SNEAK)) { if(!AFF_FLAGGED(ch, AFF_INVISIBLE)) { act("$n has arrived.", FALSE, ch, 0, 0, TO_ROOM); } } if (ch->desc != NULL) look_at_room(ch, 0); if(IS_NPC_CRAB(ch) || IS_NPC_LIVESTOCK(ch)) { for (i = world[ch->in_room].people; i; i = i->next_in_room) { if(IS_NPC_WOLF(i) && IS_NPC_CRAB(ch)) { sprintf(buf, "%s sees %s and tries to run!\r\n", GET_NAME(ch), GET_NAME(i)); send_to_room(buf, ch->in_room); if(!number(0, 2)) { do_flee(ch, NULL, 0, 0); } if(i->in_room == ch->in_room && !number(0, 2)) { hit(i, ch, TYPE_UNDEFINED); } } if((IS_NPC_SKELETON(i) || IS_NPC_WOLF(i)) && IS_NPC_LIVESTOCK(ch)) { if(ch->master) { sprintf(buf, "%s sees %s and %s in absolute terror!\r\n", GET_NAME(ch), GET_NAME(i), livestock_afraid_vocals[(int)GET_RACE(ch)]); send_to_room(buf, ch->in_room); if(!number(0, 2)) { do_flee(ch, NULL, 0, 0); } if(i->in_room == ch->in_room && !number(0, 2)) { hit(i, ch, TYPE_UNDEFINED); } } } } return (1); } if (ROOM_FLAGGED(ch->in_room, ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) { log_death_trap(ch); death_cry(ch); extract_char(ch); return (0); } return (1); }
bool mage_mob_fight(struct creature *ch, struct creature *precious_vict) { int calculate_mob_aggression(struct creature *ch, struct creature *vict); struct creature *vict = NULL; if (!is_fighting(ch)) return false; // pick an enemy if (!(vict = choose_opponent(ch, precious_vict))) return false; int aggression = calculate_mob_aggression(ch, vict); if (aggression > 75) { // extremely aggressive - just attack hard if (mage_damaging_attack(ch, vict)) return true; } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (!AFF2_FLAGGED(vict, AFF2_SLOW) && can_cast_spell(ch, SPELL_SLOW)) { cast_spell(ch, vict, NULL, NULL, SPELL_SLOW); return true; } } if (aggression > 25) { // not very aggressive - play more defensively if (can_cast_spell(ch, SPELL_FIRE_SHIELD) && !AFF2_FLAGGED(ch, AFF2_FIRE_SHIELD)) { cast_spell(ch, ch, NULL, NULL, SPELL_FIRE_SHIELD); return true; } if (can_cast_spell(ch, SPELL_BLUR) && !AFF_FLAGGED(ch, AFF_BLUR)) { cast_spell(ch, ch, NULL, NULL, SPELL_BLUR); return true; } if (can_cast_spell(ch, SPELL_ARMOR) && !affected_by_spell(ch, SPELL_ARMOR)) { cast_spell(ch, ch, NULL, NULL, SPELL_ARMOR); return true; } if (mage_damaging_attack(ch, vict)) return true; } if (aggression > 5) { // attempt to neutralize or get away if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return true; } else if (can_cast_spell(ch, SPELL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_TELEPORT); return true; } else if (can_cast_spell(ch, SPELL_LOCAL_TELEPORT)) { cast_spell(ch, vict, NULL, NULL, SPELL_LOCAL_TELEPORT); return true; } } if (mage_damaging_attack(ch, vict)) return true; return false; }
void hunt_victim(struct char_data * ch) { extern struct char_data *character_list; ACMD(do_open); int dir; byte found; struct char_data *tmp; struct char_data *hunted_ch; char abuf[80]; char doorname[80]; if (!ch || !HUNTING(ch) || AFF2_FLAGGED(ch, AFF2_MINOR_PARALIZED) || AFF_FLAGGED(ch, AFF_MAJOR_PARALIZED)) { return; } hunted_ch = find_hunted_char(HUNTING(ch)); /* make sure the char still exists */ for (found = 0, tmp = character_list; tmp && !found && hunted_ch; tmp = tmp->next) { if (HUNTING(ch) == GET_IDNUM(tmp)) { found = 1; } } if (!found) { act("$n says, 'Damn! My prey is gone!!'", TRUE, ch, 0, 0, TO_ROOM); /* don't forget vict until they die or I am dead HUNTING(ch) = 0; */ return; } /* dez 19980805 if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_SENTINEL)) { dir = find_first_step(ch->in_room, hunted_ch->in_room, 2); } else if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_STAY_ZONE)) { */ if (IS_NPC(ch) && MOB_FLAGGED(ch, MOB_STAY_ZONE)) { dir = find_first_step(ch->in_room, hunted_ch->in_room, 1); } else { dir = find_first_step(ch->in_room, hunted_ch->in_room, 0); } if (dir < 0) { sprintf(buf, "$n says 'Damn! Lost %s!'", HMHR(hunted_ch)); act(buf, TRUE, ch, 0, 0, TO_ROOM); /* don't forget vict until they die or I am dead HUNTING(ch) = 0; */ return; } else { if (IS_CLOSED(ch->in_room, dir)) { one_argument(EXIT(ch, dir)->keyword, doorname); sprintf(abuf, "%s %s", doorname, dirs[dir]); do_open(ch, abuf, 0, 0); } perform_move(ch, dir, 1); if (ch->in_room == hunted_ch->in_room && !ROOM_FLAGGED(hunted_ch->in_room, ROOM_PEACEFUL)) { if (CAN_SEE(ch, hunted_ch)) { hit(ch, hunted_ch, TYPE_UNDEFINED); } } return; } }
/* * Remove an affected_type structure from a char (called when duration * reaches zero). Pointer *af must never be NIL! Frees mem and calls * affect_location_apply */ void affect_remove(struct char_data * ch, struct affected_type * af, int output) { struct affected_type *temp; struct affected_type aff; bool accum_affect = FALSE; int k; if (ch->affected == NULL) { core_dump(); return; } switch (af->type) { case SPELL_CHARM: { struct char_data* victim = ch->master; if (output == 0) break; affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); if (ch->master) { stop_follower(ch); } if (victim) { if(IS_NPC(ch)) { SET_BIT(MOB_FLAGS(ch), MOB_AGGRESSIVE | MOB_MEMORY); } if (mag_savingthrow(victim, SAVING_SPELL)) { hit(victim, ch, TYPE_UNDEFINED); } } return; } case SPELL_LIGHT: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light -= 10; } } break; case SPELL_DARKNESS: if (output == 0) break; if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (world[ch->in_room].name != (char*) NULL) { world[ch->in_room].light += 10; } } break; case SPELL_BLACK_PLAGUE: mag_affects(30, ch, ch, SPELL_BREATH_OF_LIFE, SAVING_SPELL); break; case SPELL_CALL_ANIMAL_SPIRIT: case SPELL_ANIMAL_SUMMONING: case SPELL_ANIMAL_SUMMONING_II: case SPELL_ANIMAL_SUMMONING_III: case SPELL_CONJURE_ELEMENTAL: case SPELL_GREATER_ELEMENTAL: case SPELL_DUST_DEVIL: case SPELL_STICKS_TO_SNAKES: case SPELL_SUMMON_INSECTS: case SPELL_AERIAL_SERVANT: case SPELL_SUMMON_GUARD: if (IS_NPC(ch)) { if (GET_POS(ch) > POS_DEAD) { if (output == 1) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); GET_NAME(ch, chname); stop_fighting(ch); /*Fighting Bug Fix Jasrags*/ sprintf(buf, "%s disappears into thin air as the summoning ends.", chname); act(buf, FALSE, world[ch->in_room].people, 0, 0, TO_ROOM); FREE_NAME(chname); extract_char(ch); ch = NULL; return; } } } break; case SPELL_POLYMORPH: if (!PRF_FLAGGED(ch, PRF_NOTSELF)) { affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); return; } break; case SPELL_DONTUSEME: if(AFF_FLAGGED(ch, AFF_STANCE) && !AFF_FLAGGED(ch, AFF_TIRED)) { aff.type = SKILL_STANCE; aff.duration = 2; aff.location = APPLY_STR; aff.modifier = -2; aff.bitvector = AFF_TIRED; accum_affect = FALSE; affect_to_char(ch, &aff); } break; default: break; } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type != SPELL_POLYMORPH && af->type != SPELL_DONTUSEME) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (*spell_wear_off_msg[af->type]) { send_to_char(spell_wear_off_msg[af->type], ch); send_to_char("\r\n", ch); } } } if (output && (af->type > 0) && (af->type <= MAX_SPELLS) && af->type == SPELL_POLYMORPH) { if (!af->next || (af->next->type != af->type) || (af->next->duration > 0)) { if (PLR_FLAGGED(ch, PLR_RABBIT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_RABBIT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing, and your ears shrinking. You no longer feel like a rabbit.\r\n", ch); act("$n's body grows, $s ears shrinking. $n no longer looks like a rabbit.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BIRD)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BIRD); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel yourself growing and your feathers falling away. You no longer feel like a bird.\r\n", ch); act("$n's body grows, $s feathers falling away as it expands. $n no longer looks like a bird.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_WOLF)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_WOLF); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your your fur shed and your teeth shrink. You no longer feel like a wolf.\r\n", ch); act("$n's teeth shrink, $s fur shedding. $n no longer looks like a wolf.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_BEAR)) { REMOVE_BIT(PLR_FLAGS(ch), PLR_BEAR); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("Your claws shrink as does the rest of your body. You no longer feel like a bear.\r\n", ch); act("$n's claws shrink as does the rest of $s body. $n no longer looks like a bear.\r\n", 0, ch, 0, 0, TO_ROOM); } if (PLR_FLAGGED(ch, PLR_CAT)){ REMOVE_BIT(PLR_FLAGS(ch), PLR_CAT); REMOVE_BIT(PRF_FLAGS(ch), PRF_NOTSELF); send_to_char("You feel your body growing, and your fur shedding. You no longer feel like a cat.\r\n", ch); act("$n's body slowly grows, $s fur shedding. $n no longer looks like a cat.\r\n", 0, ch, 0, 0, TO_ROOM); } for (k = 0; k < NUM_WEARS; k++) if (GET_EQ(ch, k)){ GET_OBJ_DISGUISE(GET_EQ(ch, k)) = 0; } } } affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE); REMOVE_FROM_LIST(af, ch->affected, next); free(af); affect_total(ch); }
/* Update PCs, NPCs, and objects */ void point_update(void) { struct char_data *i, *next_char; struct obj_data *j, *next_thing, *jj, *next_thing2; /* characters */ for (i = character_list; i; i = next_char) { next_char = i->next; gain_condition(i, FULL, -1); gain_condition(i, DRUNK, -1); gain_condition(i, THIRST, -1); if (GET_POS(i) >= POS_STUNNED) { GET_HIT(i) = MIN(GET_HIT(i) + hit_gain(i), GET_MAX_HIT(i)); GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), GET_MAX_MANA(i)); GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), GET_MAX_MOVE(i)); if (AFF_FLAGGED(i, AFF_POISON)) if (damage(i, i, 2, SPELL_POISON) == -1) continue; /* Oops, they died. -gg 6/24/98 */ if (GET_POS(i) <= POS_STUNNED) update_pos(i); } else if (GET_POS(i) == POS_INCAP) { if (damage(i, i, 1, TYPE_SUFFERING) == -1) continue; } else if (GET_POS(i) == POS_MORTALLYW) { if (damage(i, i, 2, TYPE_SUFFERING) == -1) continue; } if (!IS_NPC(i)) { update_char_objects(i); if (GET_LEVEL(i) < idle_max_level) check_idling(i); } } /* objects */ for (j = object_list; j; j = next_thing) { next_thing = j->next; /* Next in object list */ /* If this is a corpse */ if (IS_CORPSE(j)) { /* timer count down */ if (GET_OBJ_TIMER(j) > 0) GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) { if (j->carried_by) act("$p decays in your hands.", FALSE, j->carried_by, j, 0, TO_CHAR); else if ((IN_ROOM(j) != NOWHERE) && (world[IN_ROOM(j)].people)) { act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_ROOM); act("A quivering horde of maggots consumes $p.", TRUE, world[IN_ROOM(j)].people, j, 0, TO_CHAR); } for (jj = j->contains; jj; jj = next_thing2) { next_thing2 = jj->next_content; /* Next in inventory */ obj_from_obj(jj); if (j->in_obj) obj_to_obj(jj, j->in_obj); else if (j->carried_by) obj_to_room(jj, IN_ROOM(j->carried_by)); else if (IN_ROOM(j) != NOWHERE) obj_to_room(jj, IN_ROOM(j)); else core_dump(); } extract_obj(j); } } /* If the timer is set, count it down and at 0, try the trigger */ /* note to .rej hand-patchers: make this last in your point-update() */ else if (GET_OBJ_TIMER(j)>0) { GET_OBJ_TIMER(j)--; if (!GET_OBJ_TIMER(j)) timer_otrigger(j); } } }
// 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); }