示例#1
0
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;
}
示例#2
0
MetaRoom *Map::metaRoomAt(unsigned int _x, unsigned int _y) {
	for (std::vector<MetaRoom *>::iterator i = metarooms.begin(); i != metarooms.end(); i++) {
		MetaRoom *r = *i;
		if ((_x >= r->x()) && (_y >= r->y()))
			if ((_x <= (r->x() + r->width())) && (_y <= (r->y() + r->height())))
				return r;
	}
	return 0;
}
示例#3
0
void Agent::updateAudio(boost::shared_ptr<AudioSource> s) {
	assert(s);
	MetaRoom *room = world.map.metaRoomAt(x, y);
	if (!room) {
		// TODO: think about inrange when positioning outside-metaroom agents
		s->setPos(x + getWidth() / 2, y + getHeight() / 2, zorder);
		return;
	}

	float xc = x;

	bool inrange = false;
	if (inrange_at(room, x, y, getWidth(), getHeight())) {
		xc = x;
		inrange = true;
	} else if (room->wraparound()) {
		if (inrange_at(room, x - room->width(), y, getWidth(), getHeight())) {
			xc = x - room->width();
			inrange = true;
		} else if (inrange_at(room, x + room->width(), y, getWidth(), getHeight())) {
			xc = x + room->width();
			inrange = true;
		}
	}
	s->setMute(!inrange);
	if (inrange)
		s->setPos(xc + getWidth() / 2, y + getHeight() / 2, zorder);
	// TODO: setVelocity?
}
示例#4
0
void Agent::moveTo(float _x, float _y, bool force) {
	// Move ourselves to the specified location.
	wasmoved = true;

	// if we're being carried and aren't being forced to move (prbly by our carrier), forget it
	if (carriedby && !force) return;
	
	// TODO: what if we move while being carried? doomy explosions ensue, that's what!
	float xoffset = _x - x;
	float yoffset = _y - y;		

	x = _x; y = _y;

	// handle wraparound
	// TODO: this is perhaps non-ideal
	if (engine.version < 3 && xoffset != 0.0f) {
		// TODO: it'd be nice to handle multiple metarooms
		MetaRoom *m = world.map.getFallbackMetaroom();
		assert(m);

		if (x < m->x()) {
			x += m->width();
		} else if (x > m->x() + m->width()) {
			x -= m->width();
		}
	}

	for (std::vector<AgentRef>::iterator i = floated.begin(); i != floated.end(); i++) {
		assert(*i);
		(*i)->moveTo((*i)->x + xoffset, (*i)->y + yoffset);
	}

	adjustCarried(xoffset, yoffset);
}
示例#5
0
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);
}
示例#6
0
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;
				}
			}
		}
	}
}
示例#7
0
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));
}
示例#8
0
bool Agent::fireScript(unsigned short event, Agent *from, caosVar one, caosVar two) {
	// Start running the specified script on the VM of this agent, with FROM set to the provided agent.

	if (dying) return false;

	CreatureAgent *c = 0;
	if (event <= 3 || event == 4 || event == 12 || event == 13 || event == 14)
		c = dynamic_cast<CreatureAgent *>(from);

	switch (event) {
		case 0: // deactivate
			if (c && !cr_can_stop) return false;
			// TODO: not sure if this is the right place to do this.
			actv.setInt(event);
			break;
		case 1: // activate 1
			if (c && !cr_can_push) return false;
			// TODO: not sure if this is the right place to do this.
			actv.setInt(event);
			break;
		case 2: // activate 2
			if (c && !cr_can_pull) return false;
			// TODO: not sure if this is the right place to do this.
			actv.setInt(event);
			break;
		case 3: // hit
			if (c && !cr_can_hit) return false;
			break;
		case 4: // pickup
			if (c && !cr_can_pickup) return false;
			if (!from) return false;
			if (from == world.hand()) {
				if (!mouseable()) return false;
			} else if (!c) {
				// TODO: valid check for vehicles?
				if (!carryable()) return false;
			}
			from->addCarried(this); // TODO: correct behaviour?
			break;
		case 5: // drop
			if (!from) return false;
			// TODO: this check isn't very good for vehicles ;p
			// if (from != carriedby) return false;
			from->dropCarried(this); // TODO: correct?
			break;
		case 12: // eat
			if (c && !cr_can_eat) return false;
			break;
		case 13: // hold hands with pointer
			if (c) {
				// TODO
			}
			break;
		case 14: // stop holding hands with pointer
			if (c) {
				// TODO
			}
			break;
		case 92: // TODO: hack for 'UI Mouse Down' event - we need a real event system!
			std::cout << "faking event 92 on " << identify() << std::endl;
			CompoundPart *p = world.partAt(world.hand()->pointerX(), world.hand()->pointerY());
			if (!p || p->getParent() != this) // if something is horridly broken here, return
				return false; // was caos_assert(p && p->getParent() == this);
			p->handleClick(world.hand()->pointerX() - p->x - p->getParent()->x, world.hand()->pointerY() - p->y - p->getParent()->y);
			// TODO: we're [obviously] missing firing the pointer script here, but it's a hack for now
			break;
	}

	bool ranscript = false;

	shared_ptr<script> s = findScript(event);
	if (s) {
		bool madevm = false;
		if (!vm) { madevm = true; vm = world.getVM(this); }
	
		if (vm->fireScript(s, event == 9, from)) {
			lastScript = event;
			zotstack();
			vm->setVariables(one, two);

			// TODO: we should set _it_ in a more sensible way
			CreatureAgent *a = dynamic_cast<CreatureAgent *>(this);
			if (a) {
				Creature *c = a->getCreature();
				assert(c);
				vm->_it_ = c->getAttentionFocus();
			}
			
			vmTick();
			ranscript = true;
		} else if (madevm) {
			world.freeVM(vm);
			vm = 0;
		}	
	}

	switch (event) {
		case 5:
			if (invehicle) break;
			if (engine.version > 1) break;

			// Creatures 1 drop snapping
			// TODO: this probably doesn't belong here, but it has to be run after the
			// drop script starts (see for instance C1 carrots, which change pose)
			MetaRoom* m = world.map.metaRoomAt(x, y);
			if (!m) break;
			shared_ptr<Room> r = m->nextFloorFromPoint(x, y);
			if (!r) break;
			moveTo(x, r->bot.pointAtX(x).y - getHeight());
			
			break;
	}
	
	return ranscript;
}