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); } } }
void SkeletalCreature::setPose(unsigned int p) { posedirection = 0; for (int i = 0; i < SkeletalPartCount(); i++) pose[i] = p; recalculateSkeleton(); }
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();*/ }
void SkeletalCreature::skeletonInit() { // TODO: the exception throwing in here needs some more thought // TODO: if we throw an exception when we need to kill the creature off, else segfault :/ for (int i = 0; i < SkeletalPartCount(); i++) { // CV hackery if (engine.version == 1) // TODO: this is hackery to skip tails for C1 if (i == 6 || i == 13) continue; // reset the existing image reference images[i].reset(); // find the relevant gene char x = cee_bodyparts[i].letter; creatureAppearanceGene *partapp = appearanceGeneForPart(x); int partspecies, partvariant; partspecies = creature->getGenus(); if (partapp) { if (engine.version > 1) partspecies = partapp->species; partvariant = partapp->variant; } else { partvariant = creature->getVariant(); } int spe = partspecies; /* * In order to find a sprite, we try our current stage first, then the stages below us, * and then we try again with all lower variants, and if that fails for female sprites * then we try the whole thing again but trying to find a male sprite. */ // find relevant sprite bool tryfemale = creature->isFemale(); while (!images[i]) { int var = partvariant; while (var > -1 && !images[i]) { int stage_to_try = creature->getStage(); while (stage_to_try > -1 && !images[i]) { images[i] = world.gallery.getImage(x + dataString(stage_to_try, tryfemale, spe, var)); stage_to_try--; } var--; } if (!tryfemale) break; tryfemale = false; } if (!images[i]) throw creaturesException(boost::str(boost::format("SkeletalCreature couldn't find an image for part %c of species %d, variant %d, stage %d") % x % (int)partspecies % (int)partvariant % (int)creature->getStage())); // find relevant ATT data std::string attfilename; int var = partvariant; while (var > -1 && attfilename.empty()) { int stage_to_try = creature->getStage(); while (stage_to_try > -1 && attfilename.empty()) { attfilename = world.findFile(std::string("/Body Data/") + x + dataString(stage_to_try, false, spe, var) + ".att"); stage_to_try--; } var--; } if (attfilename.empty()) throw creaturesException(boost::str(boost::format("SkeletalCreature couldn't find body data for part %c of species %d, variant %d, stage %d") % x % (int)partspecies % (int)partvariant % creature->getStage())); // load ATT file std::ifstream in(attfilename.c_str()); if (in.fail()) throw creaturesException(boost::str(boost::format("SkeletalCreature couldn't load body data for part %c of species %d, variant %d, stage %d (tried file %s)") % x % (int)partspecies % (int)partvariant % creature->getStage() % attfilename)); in >> att[i]; images[i] = tintBodySprite(images[i]); } }