示例#1
0
void SkeletalCreature::render(Surface *renderer, int xoffset, int yoffset) {
	bool mirror_body_parts = (world.variables["engine_mirror_creature_body_parts"] == 1);

	for (int j = 0; j < 17; j++) {
		int i = cee_zorder[posedirection][j];
		if (i >= SkeletalPartCount()) continue; // CV hackery

		if (engine.version == 1) // TODO: this is hackery to skip tails for C1
			if (i == 6 || i == 13) continue;

		bodypartinfo *part = &cee_bodyparts[i];

		unsigned int ourpose = pose[i];

		bool mirror = false;
		if (i != 14 && i != 15 && mirror_body_parts && ourpose >= 4 && ourpose <= 7) {
			ourpose -= 4;
			mirror = true;
		}

		// adjust for pregnancy/facial expressions/etc as necessary
		if (part->parent == -1) { // body
			ourpose += (pregnancy * (engine.version < 3 ? 10 : 16));
		} else if (i == 1) { // head
			ourpose += (eyesclosed ? (engine.version < 3 ? 10 : 16) : 0)
				+ (facialexpression * (engine.version < 3 ? 20 : 32));
		} else if (i == 16) { // hair
			ourpose += 0; // TODO: 16 * hair
		}

		assert(images[i]);

		renderer->render(images[i], ourpose, partx[i] + adjustx + xoffset, party[i] + adjusty + yoffset, false, 0, mirror);

		if (displaycore) {
			// TODO: we draw a lot of points twice here :)
			int atx = attachmentX(i, 0) + xoffset, aty = attachmentY(i, 0) + yoffset;
			renderer->renderLine(atx - 1, aty, atx + 1, aty, 0xFF0000CC);
			renderer->renderLine(atx, aty - 1, atx, aty + 1, 0xFF0000CC);
			atx = attachmentX(i, 1) + xoffset; aty = attachmentY(i, 1) + yoffset;
			renderer->renderLine(atx - 1, aty, atx + 1, aty, 0xFF0000CC);
			renderer->renderLine(atx, aty - 1, atx, aty + 1, 0xFF0000CC);
		}
	}
}
示例#2
0
std::pair<int, int> SkeletalCreature::getCarryPoint() {
	std::pair<int, int> carrypoint;

	// TODO: 9 is left hand, how do we work out which hand a norn is carrying with?
	carrypoint.first = attachmentX(9, 1);
	carrypoint.second = attachmentY(9, 1);

	return carrypoint;
}
示例#3
0
void SkeletalCreature::setPose(std::string s) {
	switch (s[0]) {
		case '?':
			switch (direction) {
				case 0: break; // north, TODO
				case 1: break; // south, TODO
				case 2: posedirection = 0; break; // right
				case 3: posedirection = 1; break; // left
				default: assert(false);
			}
			break;
		case '!':
			switch (direction) {
				case 0: break; // north, TODO
				case 1: break; // south, TODO
				case 2: posedirection = 1; break; // right
				case 3: posedirection = 0; break; // left
				default: assert(false);
			}
			break;
		case '0': posedirection = 3; break;
		case '1': posedirection = 2; break;
		case '2': posedirection = 0; break;
		case '3': posedirection = 1; break;
		case 'X': break; // do nothing
		default: 
			std::cout << "internal warning: SkeletalCreature::setPose didn't understand direction " << s[0] << " in pose '" << s << "'." << std::endl;
			break;
	}

	for (int i = 0; i < 14; i++) {
		int newpose;

		switch (s[i + 1]) {
			case '0': newpose = 0 + (posedirection * 4); break;
			case '1': newpose = 1 + (posedirection * 4); break;
			case '2': newpose = 2 + (posedirection * 4); break;
			case '3': newpose = 3 + (posedirection * 4); break;
			case '?': assert(i == 0); {
					// make the head look in the posedirection of _IT_
					float attachmenty = attachmentY(1, 0) + y; // head attachment point, which we'll use to 'look' from atm
					
					// TODO: this is horrible, but i have no idea how the head angle is calculated
					AgentRef attention = creature->getAttentionFocus();
					if (attention && attention->y > (attachmenty + 30)) newpose = 0;
					else if (attention && attention->y < (attachmenty - 70)) newpose = 3;
					else if (attention && attention->y < (attachmenty - 30)) newpose = 2;
					else newpose = 1;
					newpose += (posedirection * 4);
				}
				break;
			// TODO: '!' also?
			case 'X': continue; // do nothing
			default:
				  std::cout << "internal warning: SkeletalCreature::setPose didn't understand " << s[i + 1] << " in pose '" << s << "'." << std::endl;
				  continue;
		}

		pose[cee_lookup[i]] = newpose;

		// TODO: this is some hackery for CV, 
		if (world.gametype != "cv") continue;
		if (i == 0) { // head
			pose[14] = newpose; pose[15] = newpose; // ears
			pose[16] = newpose; // hair
		} else if (i == 1) {
			pose[6] = newpose; // tail root
			pose[13] = newpose; // tail tip
		}
	}
		
	recalculateSkeleton();
}
示例#4
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;
				}
			}
		}
	}
}
示例#5
0
void SkeletalCreature::recalculateSkeleton() {
	int lowestx = 0, lowesty = 0, highestx = 0, highesty = 0;

	for (int i = 0; i < SkeletalPartCount(); i++) {
		if (engine.version == 1) // TODO: this is hackery to skip tails for C1
			if (i == 6 || i == 13) continue;

		bodypartinfo *part = &cee_bodyparts[i];

		if (part->parent == -1) {
			partx[i] = 0; party[i] = 0;
		} else {
			attFile &bodyattinfo = att[0];
			attFile &attinfo = att[i];

			int attachx = att[i].attachments[pose[i]][0];
			int attachy = att[i].attachments[pose[i]][1];
			int x, y;

			if (part->parent == 0) { // linking to body
				x = bodyattinfo.attachments[pose[0]][part->attorder * 2];
				y = bodyattinfo.attachments[pose[0]][(part->attorder * 2) + 1];
			} else { // extra limb
				attFile &parentattinfo = att[part->parent];

				x = partx[part->parent] + parentattinfo.attachments[pose[part->parent]][part->attorder * 2]; 
				y = party[part->parent] + parentattinfo.attachments[pose[part->parent]][(part->attorder * 2) + 1];
			}

			x = x - attachx;
			y = y - attachy;

			partx[i] = x; party[i] = y;

			if (x < lowestx) { lowestx = x; }
			if (y < lowesty) { lowesty = y; }
			if (x + (int)images[i]->width(pose[i]) > highestx) { highestx = x + images[i]->width(pose[i]); }
			if (y + (int)images[i]->height(pose[i]) > highesty) { highesty = y + images[i]->height(pose[i]); }
		}
	}

	adjustx = -lowestx;
	adjusty = -lowesty;

	// TODO: muh, we should cooperate with physics system etc
	if (!carriedby && !invehicle && calculated) {
		int orig_footpart = (downfoot_left ? 11 : 12);
		// adjust location to match foot
		moveTo(x - (attachmentX(orig_footpart, 1) - oldfootx), y - (attachmentY(orig_footpart, 1) - oldfooty));
	}

	// work out which foot is down
	int leftfoot = attachmentY(11, 1);
	int rightfoot = attachmentY(12, 1);
	downfoot_left = (rightfoot < leftfoot);

	calculated = true;
	int orig_footpart = (downfoot_left ? 11 : 12);
	oldfootx = attachmentX(orig_footpart, 1);
	oldfooty = attachmentY(orig_footpart, 1);
	
	// recalculate width/height
	height = downfoot_left ? leftfoot : rightfoot;
	width = 50; // TODO: arbitary values bad

	// TODO: muh, we should cooperate with physics system etc
	/*if (carriedby || invehicle)
		downfootroom.reset();
	else
		snapDownFoot();*/
}
示例#6
0
void SkeletalCreature::setPose(std::string s) {
	switch (s[0]) {
		case '?': // towards object of attention
			switch (direction) {
				case 0: posedirection = 3; break; // north, TODO
				case 1: posedirection = 2; break; // south, TODO
				case 2: posedirection = 0; break; // right
				case 3: posedirection = 1; break; // left
				default: assert(false);
			}
			break;
		case '!': // away from object of attention
			switch (direction) {
				case 0: posedirection = 2; break; // north, TODO
				case 1: posedirection = 3; break; // south, TODO
				case 2: posedirection = 1; break; // right
				case 3: posedirection = 0; break; // left
				default: assert(false);
			}
			break;
		case '0': posedirection = 3; break;
		case '1': posedirection = 2; break;
		case '2': posedirection = 0; break;
		case '3': posedirection = 1; break;
		case 'X': break; // do nothing
		default: 
			std::cout << "internal warning: SkeletalCreature::setPose didn't understand direction " << s[0] << " in pose '" << s << "'." << std::endl;
			break;
	}

	for (int i = 0; i < 14; i++) {
		int newpose = -1;

		switch (s[i + 1]) {
			case '0': newpose = 0; break;
			case '1': newpose = 1; break;
			case '2': newpose = 2; break;
			case '3': newpose = 3; break;
			case '4': newpose = (engine.version < 3) ? 8 : 10; break; // 'to camera'
			case '?': assert(i == 0); { // TODO
					// make the head look in the posedirection of _IT_
					float attachmenty = attachmentY(1, 0) + y; // head attachment point, which we'll use to 'look' from atm
					
					// TODO: this is horrible, but i have no idea how the head angle is calculated
					AgentRef attention = creature->getAttentionFocus();
					if (attention && attention->y > (attachmenty + 30)) newpose = 0;
					else if (attention && attention->y < (attachmenty - 70)) newpose = 3;
					else if (attention && attention->y < (attachmenty - 30)) newpose = 2;
					else newpose = 1;
				}
				break;
			// TODO: '!' also?
			case 'X': continue; // do nothing
			default:
				  std::cout << "internal warning: SkeletalCreature::setPose didn't understand " << s[i + 1] << " in pose '" << s << "'." << std::endl;
				  continue;
		}

		assert(newpose != -1);

		if (newpose < 4) {
			// newpose gives the angle, now we need to add the offset for left/right/forward/back.

			if (engine.version < 3 && posedirection > 1)
				newpose = 6 + posedirection; // only one forward/back pose in c1/c2
			else
				newpose += (posedirection * 4);
		}

		pose[cee_lookup[i]] = newpose;

		// TODO: this is some hackery for CV, 
		if (world.gametype != "cv") continue;
		if (i == 0) { // head
			pose[14] = newpose; pose[15] = newpose; // ears
			pose[16] = newpose; // hair
		} else if (i == 1) {
			pose[6] = newpose; // tail root
			pose[13] = newpose; // tail tip
		}
	}
		
	recalculateSkeleton();
}