/* * Does falling drawbridge or portcullis miss etmp? */ static boolean e_missed(struct entity *etmp, boolean chunks) { int misses; if (automiss(etmp)) return TRUE; if (flying(etmp->emon) && (is_u(etmp) ? !u_helpless(hm_all) : (etmp->emon->mcanmove && !etmp->emon->msleeping))) /* flying requires mobility */ misses = 5; /* out of 8 */ else if (levitates(etmp->emon) || (is_u(etmp) && Levitation)) /* doesn't require mobility */ misses = 3; else if (chunks && is_pool(level, etmp->ex, etmp->ey)) misses = 2; /* sitting ducks */ else misses = 0; if (is_db_wall(etmp->ex, etmp->ey)) misses -= 3; /* less airspace */ enum rng rng = is_u(etmp) ? rng_survive_dbridge : rng_main; return (boolean) ((misses > rn2_on_rng(8, rng)) ? TRUE : FALSE); }
/* * Simple-minded "can it be here?" routine */ static boolean e_survives_at(struct entity *etmp, int x, int y) { if (noncorporeal(etmp->edata)) return TRUE; if (is_pool(level, x, y)) return (boolean) (waterwalks(etmp->emon) || unbreathing(etmp->emon) || swims(etmp->emon) || flying(etmp->emon) || levitates(etmp->emon)); /* must force call to lava_effects in e_died if is_u */ if (is_lava(level, x, y)) return (boolean) (likes_lava(etmp->edata) || flying(etmp->emon) || levitates(etmp->emon)); if (is_db_wall(x, y)) return !!phasing(etmp->emon); return TRUE; }
void Steven::update( float delta ) { //keep speed b2Body* body = getB2Body(); b2Vec2 v = body->GetLinearVelocity(); b2Vec2 impulse = skiSpeed(v); impulse *= body->GetMass(); //b2Vec2 impulse = b2Vec2( (10 - v.x)*body->GetMass(), 0); body->ApplyLinearImpulse(impulse, body->GetWorldCenter()); ////compute distance to hill b2Vec2 rayStart = this->m_pB2Body->GetWorldCenter(); b2Vec2 rayEnd = b2Vec2(rayStart.x, rayStart.y - 100); class RayCastCallback : public b2RayCastCallback { virtual float32 ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float32 fraction) { CCString* name = b2Helper::getBodyName(fixture->GetBody()); if (name->compare("hill") == 0) { Steven* steven = Steven::sharedSteven(); steven->mSkiHigh = (steven->m_pB2Body->GetWorldCenter().y - point.y) * G.PTM_RATIO - mRadius; return 0; } return 1; } } callback; G.world->RayCast(&callback,rayStart, rayEnd); //auto rotation in sky if (flying()) { rotationBy(-30 * delta); } if (flying() && mStatus == StevenStatus::SS_Ski) { fly(); } }
void move_sound(ter_num_t ter,short step){ static bool on_swamp = false; short pic; eTerSpec spec; pic = univ.scenario.ter_types[ter].picture; spec = univ.scenario.ter_types[ter].special; eStepSnd snd = univ.scenario.ter_types[ter].step_sound; // if on swamp don't play squish sound : BoE legacy behavior, can be removed safely if(snd == eStepSnd::SPLASH && !flying() && univ.party.in_boat < 0){ if(on_swamp && get_ran(1,1,100) >= 10) return; on_swamp = true; } else on_swamp = false; if(!monsters_going && (overall_mode < MODE_COMBAT) && (univ.party.in_boat >= 0)) { if(spec == eTerSpec::TOWN_ENTRANCE) return; play_sound(48); //play boat sound } else if(!monsters_going && (overall_mode < MODE_COMBAT) && (univ.party.in_horse >= 0)) { play_sound(85); //so play horse sound } else switch(univ.scenario.ter_types[ter].step_sound){ case eStepSnd::SQUISH: play_sound(55); break; case eStepSnd::CRUNCH: play_sound(47); break; case eStepSnd::NONE: break; case eStepSnd::SPLASH: play_sound(17); break; case eStepSnd::STEP: if(step % 2 == 0) //footsteps alternate sound play_sound(49); else play_sound(50); } }
/* Generate earthquake :-) of desired force. That is: create random chasms (pits). Currently assumes that the player created it (you'll need to change at least messages, angering, and kill credit if you generalize it). */ static void do_earthquake(int force) { int x, y; struct monst *mtmp; struct obj *otmp; struct trap *chasm, *oldtrap; int start_x, start_y, end_x, end_y; start_x = youmonst.mx - (force * 2); start_y = youmonst.my - (force * 2); end_x = youmonst.mx + (force * 2); end_y = youmonst.my + (force * 2); if (start_x < 0) start_x = 0; if (start_y < 0) start_y = 0; if (end_x >= COLNO) end_x = COLNO - 1; if (end_y >= ROWNO) end_y = ROWNO - 1; for (x = start_x; x <= end_x; x++) for (y = start_y; y <= end_y; y++) { if ((mtmp = m_at(level, x, y)) != 0) { wakeup(mtmp, FALSE); /* peaceful monster will become hostile */ if (mtmp->mundetected && is_hider(mtmp->data)) { mtmp->mundetected = 0; if (cansee(x, y)) pline(msgc_youdiscover, "%s is shaken loose from %s!", Amonnam(mtmp), mtmp->data == &mons[PM_TRAPPER] ? "its hiding place" : the(ceiling(youmonst.mx, youmonst.my))); else You_hear(msgc_levelsound, "a thumping sound."); if (x == youmonst.mx && y == youmonst.my && mtmp->data != &mons[PM_TRAPPER]) pline(msgc_moncombatgood, "You easily dodge the falling %s.", mon_nam(mtmp)); newsym(x, y); } } if (!rn2(14 - force)) switch (level->locations[x][y].typ) { case FOUNTAIN: /* Make the fountain disappear */ if (cansee(x, y)) pline(msgc_consequence, "The fountain falls into a chasm."); goto do_pit; case SINK: if (cansee(x, y)) pline(msgc_consequence, "The kitchen sink falls into a chasm."); goto do_pit; case ALTAR: if (level->locations[x][y].altarmask & AM_SANCTUM) break; if (cansee(x, y)) pline(msgc_consequence, "The altar falls into a chasm."); goto do_pit; case GRAVE: if (cansee(x, y)) pline(msgc_consequence, "The headstone topples into a chasm."); goto do_pit; case THRONE: if (cansee(x, y)) pline(msgc_consequence, "The throne falls into a chasm."); /* Falls into next case */ case ROOM: case CORR: /* Try to make a pit */ /* Pits, spiked pits, holes, trapdoors, vibrating squares, magic portals are immune. A bear trap will leave the trap in the pit. It would be kind of cool to make landmines detonate, but that's more trouble than it's worth. */ if ((oldtrap = t_at(level, x, y))) { if (oldtrap->ttyp == PIT || oldtrap->ttyp == SPIKED_PIT || oldtrap->ttyp == HOLE || oldtrap->ttyp == TRAPDOOR || oldtrap->ttyp == VIBRATING_SQUARE || oldtrap->ttyp == MAGIC_PORTAL) break; if (oldtrap->ttyp == BEAR_TRAP) { if (mtmp) mtmp->mtrapped = 0; cnv_trap_obj(level, BEARTRAP, 1, oldtrap); } } do_pit: chasm = maketrap(level, x, y, PIT, rng_main); if (!chasm) break; /* no pit if portal at that location */ chasm->tseen = 1; level->locations[x][y].doormask = 0; mtmp = m_at(level, x, y); if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) { if (cansee(x, y)) pline(msgc_consequence, "KADOOM! The boulder falls into a chasm%s!", ((x == youmonst.mx) && (y == youmonst.my)) ? " below you" : ""); if (mtmp) mtmp->mtrapped = 0; obj_extract_self(otmp); flooreffects(otmp, x, y, ""); break; } /* We have to check whether monsters or player falls in a chasm... */ if (mtmp) { if (!flying(mtmp) && !levitates(mtmp) && !is_clinger(mtmp->data)) { mtmp->mtrapped = 1; if (cansee(x, y)) pline(combat_msgc(&youmonst, mtmp, cr_hit), "%s falls into a chasm!", Monnam(mtmp)); else if (humanoid(mtmp->data)) You_hear(msgc_levelsound, "a scream!"); mselftouch(mtmp, "Falling, ", &youmonst); if (!DEADMONSTER(mtmp)) if ((mtmp->mhp -= rnd(6)) <= 0) { if (!cansee(x, y)) pline(msgc_kill, "It is destroyed!"); else { pline(msgc_petfatal, "You destroy %s!", mtmp->mtame ? x_monnam(mtmp, ARTICLE_THE, "poor", mx_name(mtmp) ? SUPPRESS_SADDLE : 0, FALSE) : mon_nam(mtmp)); } xkilled(mtmp, 0); } } } else if (!u.utrap && x == youmonst.mx && y == youmonst.my) { if (Levitation || Flying || is_clinger(youmonst.data)) { pline(msgc_noconsequence, "A chasm opens up under you!"); pline(msgc_noconsequence, "You don't fall in!"); } else { pline(msgc_badidea, "You fall into a chasm!"); u.utrap = rn1(6, 2); u.utraptype = TT_PIT; turnstate.vision_full_recalc = TRUE; losehp(rnd(6), "fell into a chasm"); selftouch("Falling, you", "falling into a chasm while wielding"); } } else newsym(x, y); break; case DOOR: /* Make the door collapse */ if (level->locations[x][y].doormask == D_NODOOR) goto do_pit; if (cansee(x, y)) pline(msgc_consequence, "The door collapses."); if (*in_rooms(level, x, y, SHOPBASE)) add_damage(x, y, 0L); level->locations[x][y].doormask = D_NODOOR; unblock_point(x, y); newsym(x, y); break; } } }
static void do_entity(struct entity *etmp) { int newx, newy, at_portcullis, oldx, oldy; boolean must_jump = FALSE, relocates = FALSE, e_inview; struct rm *crm; if (!etmp->edata) return; /* TODO: Long worms? */ e_inview = e_canseemon(etmp); oldx = etmp->ex; oldy = etmp->ey; at_portcullis = is_db_wall(oldx, oldy); crm = &level->locations[oldx][oldy]; enum msg_channel miss_msgc, hit_msgc; if (is_u(etmp)) { miss_msgc = msgc_fatalavoid; hit_msgc = msgc_fatal_predone; } else if (etmp->emon->mtame && canspotmon(etmp->emon)) miss_msgc = hit_msgc = msgc_petfatal; else miss_msgc = hit_msgc = msgc_monneutral; if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) { if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ))) pline(miss_msgc, "The %s passes through %s!", at_portcullis ? "portcullis" : "drawbridge", e_nam(etmp)); if (is_u(etmp)) spoteffects(FALSE); return; } if (e_missed(etmp, FALSE)) { if (at_portcullis) pline(miss_msgc, "The portcullis misses %s!", e_nam(etmp)); if (e_survives_at(etmp, oldx, oldy)) return; else { if (at_portcullis) must_jump = TRUE; else relocates = TRUE; /* just ride drawbridge in */ } } else { if (crm->typ == DRAWBRIDGE_DOWN) { pline(hit_msgc, "%s crushed underneath the drawbridge.", E_phrase(etmp, "are")); /* no jump */ e_died(etmp, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "a falling drawbridge")); /* no corpse */ return; /* Note: Beyond this point, we know we're */ } /* not at an opened drawbridge, since all */ must_jump = TRUE; /* *missable* creatures survive on the */ } /* square, and all the unmissed ones die. */ if (must_jump) { if (at_portcullis) { if (e_jumps(etmp)) { relocates = TRUE; } else { if (e_inview) pline(hit_msgc, "%s crushed by the falling portcullis!", E_phrase(etmp, "are")); else You_hear(msgc_levelsound, "a crushing sound."); e_died(etmp, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "a falling portcullis")); /* no corpse */ return; } } else { /* tries to jump off bridge to original square */ relocates = !e_jumps(etmp); } } /* Here's where we try to do relocation. Assumes that etmp is not arriving at the portcullis square while the drawbridge is falling, since this square would be inaccessible (i.e. etmp started on drawbridge square) or unnecessary (i.e. etmp started here) in such a situation. */ newx = oldx; newy = oldy; find_drawbridge(&newx, &newy); if ((newx == oldx) && (newy == oldy)) get_wall_for_db(&newx, &newy); if (relocates && (e_at(newx, newy))) { /* Standoff problem: one or both entities must die, and/or both switch places. Avoid infinite recursion by checking first whether the other entity is staying put. Clean up if we happen to move/die in recursion. */ struct entity *other; other = e_at(newx, newy); if (e_survives_at(other, newx, newy) && automiss(other)) { relocates = FALSE; /* "other" won't budge */ } else { while ((e_at(newx, newy) != 0) && (e_at(newx, newy) != etmp)) do_entity(other); if (e_at(oldx, oldy) != etmp) { return; } } } if (relocates && !e_at(newx, newy)) { /* if e_at() entity = worm tail */ if (!is_u(etmp)) { remove_monster(level, etmp->ex, etmp->ey); place_monster(etmp->emon, newx, newy, TRUE); update_monster_region(etmp->emon); } else { youmonst.mx = newx; youmonst.my = newy; } etmp->ex = newx; etmp->ey = newy; e_inview = e_canseemon(etmp); } if (is_db_wall(etmp->ex, etmp->ey)) { if (e_inview) { if (is_u(etmp)) { pline(msgc_nonmonbad, "You tumble towards the closed portcullis!"); if (automiss(etmp)) pline(miss_msgc, "You pass through it!"); else pline(e_survives_at(etmp, etmp->ex, etmp->ey) ? miss_msgc : hit_msgc, "The drawbridge closes in..."); } else pline(hit_msgc, "%s behind the drawbridge.", E_phrase(etmp, "disappear")); } if (!e_survives_at(etmp, etmp->ex, etmp->ey)) { e_died(etmp, 0, CRUSHING, killer_msg(CRUSHING, "a closing drawbridge")); return; } } else { if (is_pool(level, etmp->ex, etmp->ey) && !e_inview) You_hear(msgc_levelsound, "a splash."); if (e_survives_at(etmp, etmp->ex, etmp->ey)) { if (e_inview && !flying(etmp->emon) && !levitates(etmp->emon)) pline(miss_msgc, "%s from the bridge.", E_phrase(etmp, "fall")); return; } if (is_pool(level, etmp->ex, etmp->ey) || is_lava(level, etmp->ex, etmp->ey)) if (e_inview && !is_u(etmp)) { /* drown() will supply msgs if nec. */ boolean lava = is_lava(level, etmp->ex, etmp->ey); if (Hallucination) pline(hit_msgc, "%s the %s and disappears.", E_phrase(etmp, "drink"), lava ? "lava" : waterbody_name(etmp->ex, etmp->ey)); else pline(hit_msgc, "%s into the %s.", E_phrase(etmp, "fall"), lava ? "lava" : waterbody_name(etmp->ex, etmp->ey)); } e_died(etmp, e_inview ? 3 : 2, /* CRUSHING is arbitrary */ (is_pool(level, etmp->ex, etmp->ey)) ? DROWNING : (is_lava(level, etmp->ex, etmp->ey)) ? BURNING : CRUSHING, "fell from a drawbridge"); /* no corpse */ return; } }