bool Agent::validInRoomSystem(Point p, float w, float h, int testperm) { // Return true if this agent is inside the world room system at the specified point, or false if it isn't. MetaRoom *m = world.map.metaRoomAt(p.x, p.y); if (!m) return false; for (unsigned int i = 0; i < 4; i++) { Point src, dest; switch (i) { case 0: src = boundingBoxPoint(0, p, w, h); dest = boundingBoxPoint(3, p, w, h); break; // left to bottom case 1: src = boundingBoxPoint(1, p, w, h); dest = boundingBoxPoint(3, p, w, h); break; // right to bottom case 2: src = boundingBoxPoint(2, p, w, h); dest = boundingBoxPoint(0, p, w, h); break; // top to left case 3: src = boundingBoxPoint(2, p, w, h); dest = boundingBoxPoint(1, p, w, h); break; // top to right } if (engine.version == 2) { // Creatures 2 physics int dx = dest.x - src.x; int dy = dest.y - src.y; Point deltapt(0,0); double delta = 1000000000; bool collided = false; // TODO: check suffercollisions? // TODO: muh, provided direction here is kinda a hack findCollisionInDirection((i < 2) ? 3 : 2, m, src, dx, dy, deltapt, delta, collided, true); if (collided) return false; } else { // Creatures 3 physics float srcx = src.x, srcy = src.y; shared_ptr<Room> ourRoom = m->roomAt(srcx, srcy); if (!ourRoom) return false; unsigned int dir; Line wall; world.map.collideLineWithRoomSystem(src, dest, ourRoom, src, wall, dir, testperm); if (src != dest) return false; } } return true; }
shared_ptr<Room> Map::roomAt(float _x, float _y) { MetaRoom *m = metaRoomAt((unsigned int)_x, (unsigned int)_y); // TODO: good casts? if (!m) return shared_ptr<Room>(); return m->roomAt(_x, _y); }
void SkeletalCreature::snapDownFoot() { // TODO: this isn't very well thought-out. int orig_footpart = (downfoot_left ? 11 : 12); float footx = x + attachmentX(orig_footpart, 1); float footy = y + attachmentY(orig_footpart, 1); MetaRoom *m = world.map.metaRoomAt(x, y); if (!m) return; // TODO: exceptiony death shared_ptr<Room> newroom; if (downfootroom) { if (downfootroom->containsPoint(footx, footy)) { newroom = downfootroom; } else { if (downfootroom->x_left <= footx && downfootroom->x_right >= footx) { newroom = downfootroom; // TODO, we're just forcing for now } else { float ydiff = 10000.0f; // TODO: big number for (std::map<weak_ptr<Room>,RoomDoor *>::iterator i = downfootroom->doors.begin(); i != downfootroom->doors.end(); i++) { shared_ptr<Room> thisroom = i->first.lock(); if (engine.version == 2 && size.getInt() > i->second->perm) continue; if (thisroom->x_left <= footx && thisroom->x_right >= footx) { float thisydiff = fabs(footy - thisroom->floorYatX(footx)); if (thisydiff < ydiff) { newroom = thisroom; ydiff = thisydiff; } } } } } } else { newroom = bestRoomAt(footx, footy, 3, m, shared_ptr<Room>()); // insane emergency handling float newfooty = footy; while (!newroom && newfooty > (footy - 500.0f)) { newroom = m->roomAt(footx, newfooty); newfooty--; } // TODO: give up here footy = newfooty; } bool newroomchosen = (newroom != downfootroom) && downfootroom; bool hadroom = (downfootroom); downfootroom = newroom; if (!downfootroom /*|| !falling */) { // TODO: hackery to cope with scripts moving us, this needs handling correctly somewhere if (fabs(lastgoodfootx - attachmentX(orig_footpart, 1) - x) > 50.0f || fabs(lastgoodfooty - attachmentY(orig_footpart, 1) - y) > 50.0f) { downfootroom = bestRoomAt(footx, footy, 3, m, shared_ptr<Room>()); if (downfootroom) { snapDownFoot(); return; } else { std::cout << "Creature out of room system at (" << footx << ", " << footy << ")!" << std::endl; // TODO: exceptiony death? return; } } // We fell out of the room system! How did that happen? Push ourselves back in, run collision script. std::cout << "Creature out of room system at (" << footx << ", " << footy << "), pushing it back in." << std::endl; // TODO: sucky code x = lastgoodfootx - attachmentX(orig_footpart, 1); footx = lastgoodfootx; footy = lastgoodfooty; downfootroom = m->roomAt(footx, footy); queueScript(6); if (!downfootroom) { std::cout << "no down foot room! (" << footx << ", " << footy << ")" << std::endl; // TODO: exceptiony death return; } } bool belowfloor = false; float newy = downfootroom->floorYatX(footx); if (engine.version == 2 && hadroom && y > newy) { // TODO: hilar hack: cope with walking below floors belowfloor = true; newy = downfootroom->bot.pointAtX(footx).y; } if (engine.version > 1) { // TODO: hilar hack: enable gravity if we're snapping by much if (newroomchosen && abs(y - (newy - (footy - y))) > 20) { falling = true; return; } } moveTo(x, newy - (footy - y)); lastgoodfootx = footx; lastgoodfooty = footy; if (engine.version > 2) { if (engine.version == 2 && !belowfloor && downfootroom->floorpoints.size()) { // TODO: hilar hack: same as above for floorvalue if (size.getInt() <= downfootroom->floorvalue.getInt()) { falling = true; return; } } else { // TODO: hilar hack: same as above for perm shared_ptr<Room> downroom = world.map.roomAt(footx, downfootroom->y_left_floor + 1); if (downfootroom->doors.find(downroom) != downfootroom->doors.end()) { int permsize = (engine.version == 2 ? size.getInt() : perm); if (permsize <= downfootroom->doors[downroom]->perm) { falling = true; return; } } } } }
shared_ptr<Room> roomContainingAgent(AgentRef agent) { MetaRoom *m = world.map.metaRoomAt(agent->x, agent->y); if (!m) return shared_ptr<Room>(); return m->roomAt(agent->x + (agent->getWidth() / 2.0f), agent->y + (agent->getHeight() / 2.0f)); }