1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-08-28 00:12:18 +00:00

bunny playershape, ratling playershape, refactored playershapes

This commit is contained in:
Zeno Rogue 2025-08-17 03:08:21 +02:00
parent 152b32425b
commit d17c91a9a8
4 changed files with 340 additions and 216 deletions

View File

@ -997,11 +997,7 @@ EX string csnameid(int id) {
if(id == 1) return XLAT("female");
if(id == 2) return XLAT("Prince");
if(id == 3) return XLAT("Princess");
if(id == 4 || id == 5) return XLAT("cat");
if(id == 6 || id == 7) return XLAT("dog");
if(id == 8 || id == 9) return XLATN("Familiar");
if(id == 10 || id == 11) return XLATN("spaceship");
return XLAT("none");
return XLAT(playershapes[id >> 1].name);
}
EX string csname(charstyle& cs) {
@ -3566,6 +3562,29 @@ EX void switchcolor(unsigned int& c, unsigned int* cs) {
double cc_footphase;
int lmousex, lmousey;
EX void pick_player_shape() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
dialog::init(XLAT("Choose character"));
charstyle& cs = getcs();
for(int i=0; i<pshGUARD; i++) {
dialog::addBoolItem(XLAT(playershapes[i].name), i == (cs.charid>>1), 'a'+i);
dialog::add_action([i, &cs] {
if(i == pshPrincess) {
if(!princess::everSaved && !autocheat && !unlock_all) {
addMessage(XLAT("Save %the1 first!", moPrincess));
return;
}
}
cs.charid = (cs.charid & 1) | (i << 1);
});
}
dialog::addSelItem("variant", XLAT((cs.charid & 1) ? "female" : "male"), 'x');
dialog::add_action([&cs] { cs.charid ^= 1; });
dialog::addBack();
dialog::display();
}
EX void showCustomizeChar() {
cc_footphase += hypot(mousex - lmousex, mousey - lmousey);
@ -3577,6 +3596,7 @@ EX void showCustomizeChar() {
if(shmup::on || multi::players) multi::cpid = multi::cpid_edit % multi::players;
charstyle& cs = getcs();
auto id = ePlayershape(cs.charid >> 1);
dialog::addSelItem(XLAT("character"), csname(cs), 'g');
dialog::addColorItem(XLAT("skin color"), cs.skincolor, 's');
@ -3588,7 +3608,7 @@ EX void showCustomizeChar() {
dialog::addColorItem(XLAT("bowstring color"), cs.bowcolor2, 'c');
}
if(cs.charid >= 1) dialog::addColorItem(XLAT("dress color"), cs.dresscolor, 'd');
if(id != pshRogue) dialog::addColorItem(XLAT("dress color"), cs.dresscolor, 'd');
else dialog::addBreak(100);
if(cs.charid == 3) dialog::addColorItem(XLAT("dress color II"), cs.dresscolor2, 'f');
else dialog::addBreak(100);
@ -3624,11 +3644,7 @@ EX void showCustomizeChar() {
charstyle& cs = getcs();
bool cat = cs.charid >= 4;
if(uni == 'a') { multi::cpid_edit++; multi::cpid_edit %= 60; }
else if(uni == 'g') {
cs.charid++;
if(cs.charid == 2 && !princess::everSaved && !autocheat) cs.charid = 4;
cs.charid %= 12;
}
else if(uni == 'g') pushScreen(pick_player_shape);
else if(uni == 'p') vid.samegender = !vid.samegender;
else if(uni == 's') switchcolor(cs.skincolor, cat ? haircolors : skincolors);
else if(uni == 'h') switchcolor(cs.haircolor, haircolors);
@ -4471,10 +4487,19 @@ EX void set_char_by_name(charstyle& cs, const string& s) {
cs.eyecolor = 0x500040FF;
cs.swordcolor = 0x808080FF;
}
else if(s == "felix") {
cs.charid = 12;
cs.skincolor = 0xD0D0D0FF;
cs.haircolor = 0xF0F0F0FF;
cs.dresscolor =0xF0F0F0FF;
cs.eyecolor = 0xFF0000FF;
cs.swordcolor = 0x808080FF;
}
else {
cs.charid = atoi(s.c_str());
cs.lefthanded = cs.charid >= 10;
cs.charid %= 10;
cs.lefthanded = cs.charid >= 100;
cs.charid %= 100;
cs.charid %= (2 * pshGUARD);
}
}

View File

@ -386,7 +386,9 @@ hpcshape
hpcshape shChristmasLight, shSmallPike;
hpcshape shReserved[8];
hpcshape shBunnyBody, shBunnyHead, shBunnyEar, shBunnyTail;
hpcshape shReserved[16];
int orb_inner_ring; //< for shDisk* shapes, the number of vertices in the inner ring
int res1, res2;

483
graph.cpp
View File

@ -671,6 +671,13 @@ transmatrix otherbodyparts(const shiftmatrix& V, color_t col, eMonster who, doub
// todo
auto who1 = who;
if(who == moPlayer) {
charstyle& cs = getcs();
auto id = ePlayershape(cs.charid >> 1);
if(id == pshRatling) who1 = moRatling;
}
if(detaillevel >= 2 && GDIM == 2) {
shiftmatrix VL = at_smart_lof(V, cgi.LEG1);
queuepoly(VL * xpush(rightfoot*3/4), cgi.shHumanLeg, col);
@ -716,7 +723,7 @@ transmatrix otherbodyparts(const shiftmatrix& V, color_t col, eMonster who, doub
queuepoly(Tleft, cgi.shSkeletalFoot, col);
return spin(rightfoot * wobble);
}
else if(isTroll(who) || who == moMonkey || who == moYeti || who == moRatling || who == moRatlingAvenger || who == moGoblin) {
else if(isTroll(who1) || among(who1, moMonkey, moYeti, moRatling, moRatlingAvenger, moGoblin)) {
queuepoly(Tright, cgi.shYetiFoot, col);
queuepoly(Tleft, cgi.shYetiFoot, col);
}
@ -1331,21 +1338,261 @@ EX void drawTerraWarrior(const shiftmatrix& V, int t, int hp, double footphase)
}
#endif
#if HDR
struct playershape {
string name;
bool is_humanoid;
bool is_animal;
};
enum ePlayershape { pshRogue, pshPrincess, pshCat, pshDog, pshFamiliar, pshSpaceship, pshBunny, pshRatling, pshGUARD };
#endif
EX vector<playershape> playershapes = {
{"Rogue", true, false},
{"Princess", true, false},
{"cat", false, true},
{"dog", false, true},
{"Familiar", false, true},
{"spaceship", false, false},
{"bunny", false, true},
{"Ratling", true, false}
};
EX void drawPlayer_animal(eMonster m, cell *where, const shiftmatrix& V0, color_t col, double footphase, bool stop IS(false)) {
charstyle& cs = getcs();
auto id = ePlayershape(cs.charid >> 1);
auto V = V0;
if(id == pshBunny) {
auto z2 = WDIM == 3 ? 0 : GDIM == 3 ? -abs(sin(footphase * TAU)) * cgi.human_height/3 : geom3::lev_to_factor(abs(sin(footphase * TAU)) * cgi.human_height * 2);
auto V0 = V;
V = at_smart_lof(V0, z2);
}
if(id == pshBunny) {
/* bunny */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VALEGS, cgi.shCatLegs, fc(500, cs.dresscolor, 4));
}
else {
ShadowV(V, cgi.shBunnyBody);
if(stop) return;
animallegs(VALEGS, moRunDog, fc(500, cs.dresscolor, 4), footphase);
}
queuepoly(VABODY, cgi.shBunnyTail, fc(0, cs.skincolor, 0));
queuepoly(VABODY, cgi.shBunnyBody, fc(0, cs.skincolor, 0));
queuepoly(VAHEAD, cgi.shBunnyHead, fc(150, cs.haircolor, 2));
}
else if(id == pshFamiliar) {
/* famililar */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VALEGS, cgi.shWolfLegs, fc(150, cs.dresscolor, 4));
}
else {
ShadowV(V, cgi.shWolfBody);
if(stop) return;
animallegs(VALEGS, moWolf, fc(500, cs.dresscolor, 4), footphase);
}
queuepoly(VABODY, cgi.shWolfBody, fc(0, cs.skincolor, 0));
queuepoly(VAHEAD, cgi.shFamiliarHead, fc(500, cs.haircolor, 2));
}
else if(id == pshDog) {
/* dog */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VABODY, cgi.shDogBody, fc(0, cs.skincolor, 0));
}
else {
ShadowV(V, cgi.shDogTorso);
if(stop) return;
animallegs(VALEGS, moRunDog, fc(500, cs.dresscolor, 4), footphase);
queuepoly(VABODY, cgi.shDogTorso, fc(0, cs.skincolor, 0));
}
queuepoly(VAHEAD, cgi.shDogHead, fc(150, cs.haircolor, 2));
}
else if(id == pshCat) {
/* cat */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VALEGS, cgi.shCatLegs, fc(500, cs.dresscolor, 4));
}
else {
ShadowV(V, cgi.shCatBody);
if(stop) return;
animallegs(VALEGS, moRunDog, fc(500, cs.dresscolor, 4), footphase);
}
queuepoly(VABODY, cgi.shCatBody, fc(0, cs.skincolor, 0));
queuepoly(VAHEAD, cgi.shCatHead, fc(150, cs.haircolor, 2));
}
if(!shmup::on || shmup::curtime >= shmup::getPlayer()->nextshot) {
color_t col = items[itOrbDiscord] ? watercolor(0) : fc(314, cs.eyecolor, 3);
if(among(id, pshCat, pshBunny)) {
queuepoly(VAHEAD * xpush(.04), cgi.shWolf1, col);
queuepoly(VAHEAD * xpush(.04), cgi.shWolf2, col);
}
if(id == pshDog) {
queuepoly(VAHEAD, cgi.shWolf1, col);
queuepoly(VAHEAD, cgi.shWolf2, col);
}
if(id == pshFamiliar) {
queuepoly(VAHEAD, cgi.shFamiliarEye, col);
queuepoly(VAHEAD * lmirror(), cgi.shFamiliarEye, col);
}
}
if(id == pshBunny) {
queuepoly(VAHEAD, cgi.shBunnyEar, fc(150, cs.haircolor, 2));
queuepoly(VAHEAD * MirrorY, cgi.shBunnyEar, fc(150, cs.haircolor, 2));
}
if(id == pshDog) {
color_t colnose = items[itOrbDiscord] ? watercolor(0) : fc(314, 0xFF, 3);
queuepoly(VAHEAD, cgi.shWolf3, colnose);
}
#if CAP_COMPLEX2
if(camelot::knighted)
queuepoly(VABODY, cgi.shKnightCloak, darkena(cloakcolor(camelot::knighted), 1, 0xFF));
#endif
if(tortoise::seek())
tortoise::draw(VABODY, tortoise::seekbits, 4, 0);
}
EX void drawPlayer_humanoid(eMonster m, cell *where, const shiftmatrix& V, color_t col, double footphase, bool stop IS(false)) {
charstyle& cs = getcs();
auto id = ePlayershape(cs.charid >> 1);
auto& body = (id == pshRatling) ? cgi.shYeti : (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody;
ShadowV(V, body);
if(stop) return;
const transmatrix VBS = otherbodyparts(V, fc(0, (id == pshRatling) ? cs.dresscolor : cs.skincolor, 0), items[itOrbFish] ? moWaterElemental : moPlayer, footphase);
queuepoly(VBODY * VBS, body, fc(0, cs.skincolor, 0));
if(cs.charid&1)
queuepoly(VBODY1 * VBS, cgi.shFemaleDress, fc(500, cs.dresscolor, 4));
if(cs.charid == 2)
queuepoly(VBODY2 * VBS, cgi.shPrinceDress, fc(400, cs.dresscolor, 5));
if(cs.charid == 3)
queuepoly(VBODY2 * VBS, cgi.shPrincessDress, fc(400, cs.dresscolor2, 5));
if(items[itOrbSide3])
queuepoly(VBODY * VBS, (cs.charid&1) ? cgi.shFerocityF : cgi.shFerocityM, fc(0, cs.skincolor, 0));
if(items[itOrbHorns]) {
queuepoly(VBODY * VBS, cgi.shBullHead, items[itOrbDiscord] ? watercolor(0) : 0xFF000030);
queuepoly(VBODY * VBS, cgi.shBullHorn, items[itOrbDiscord] ? watercolor(0) : 0xFF000040);
queuepoly(VBODY * VBS * lmirror(), cgi.shBullHorn, items[itOrbDiscord] ? watercolor(0) : 0xFF000040);
}
if(items[itOrbSide1] && !shmup::on)
queuepoly(VBODY * VBS * spin(-15._deg), cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, fc(314, cs.swordcolor, 3)); // 3 not colored
shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * lmirror() : VBODY * VBS;
if(peace::on) ;
else if(racing::on) {
#if CAP_RACING
if(racing::trophy[multi::cpid])
queuepoly(VWPN, cgi.shTrophy, racing::trophy[multi::cpid]);
#endif
}
else if(bow::crossbow_mode() && cs.charid < 4) {
queuepoly(VWPN, cgi.shCrossbow, fc(314, cs.bowcolor, 3));
int ti = items[itCrossbow];
if(shmup::on) {
ti = shmup::getPlayer()->nextshot - shmup::curtime;
if(ti <= 0) ti = 0;
else ti = 1 + ti / 500;
}
shiftmatrix VWPN1 = VWPN, VWPN2 = VWPN;
if(GDIM == 3) { ld h = cgi.human_height; VWPN1 = VWPN * lzpush(-h/60); VWPN2 = VWPN * lzpush(-h/30); }
if(ti <= 1) queuepoly(VWPN1, cgi.shCrossbowstringLoaded, fc(314, cs.bowcolor2, 3));
else if(ti <= 2) queuepoly(VWPN1, cgi.shCrossbowstringSemiloaded, fc(314, cs.bowcolor2, 3));
else queuepoly(VWPN1, cgi.shCrossbowstringUnloaded, fc(314, cs.bowcolor2, 3));
if(ti == 0) queuepoly(VWPN2, cgi.shCrossbowBolt, fc(314, cs.swordcolor, 3));
}
else if(items[itOrbThorns])
queuepoly(VWPN, cgi.shHedgehogBladePlayer, items[itOrbDiscord] ? watercolor(0) : 0x00FF00FF);
else if(!shmup::on && items[itOrbDiscord])
queuepoly(VWPN, cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, watercolor(0));
else if(items[itRevolver])
queuepoly(VWPN, cgi.shGunInHand, fc(314, cs.swordcolor, 3)); // 3 not colored
else if(items[itOrbSlaying]) {
queuepoly(VWPN, cgi.shFlailTrunk, items[itOrbDiscord] ? watercolor(0) : fc(314, cs.swordcolor, 3));
queuepoly(VWPN, cgi.shHammerHead, items[itOrbDiscord] ? watercolor(50) : fc(314, cs.swordcolor, 3));
}
else if(items[itCurseWeakness]) {
/* no weapon shown */
}
else if(!shmup::on)
queuepoly(VWPN, cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, fc(314, cs.swordcolor, 3)); // 3 not colored
else if(shmup::curtime >= shmup::getPlayer()->nextshot)
queuepoly(VWPN, cgi.shPKnife, fc(314, cs.swordcolor, 3)); // 3 not colored
if(items[itOrbBeauty]) {
if(cs.charid&1)
queuepoly(VHEAD1, cgi.shFlowerHair, darkena(iinf[itOrbBeauty].color, 0, 0xFF));
else
queuepoly(VWPN, cgi.shFlowerHand, darkena(iinf[itOrbBeauty].color, 0, 0xFF));
}
if(where && where->land == laWildWest) {
queuepoly(VHEAD1, cgi.shWestHat1, darkena(cs.swordcolor, 1, 0XFF));
queuepoly(VHEAD2, cgi.shWestHat2, darkena(cs.swordcolor, 0, 0XFF));
}
if(cheater && !autocheat) {
queuepoly(VHEAD1, (cs.charid&1) ? cgi.shGoatHead : cgi.shDemon, darkena(0xFFFF00, 0, 0xFF));
// queuepoly(V, shHood, darkena(0xFF00, 1, 0xFF));
}
else if(id == pshRatling) {
queuepoly(VHEAD, cgi.shRatHead, fc(500, cs.haircolor, 1));
queuepoly(VHEAD, cgi.shWolf1, cs.eyecolor);
queuepoly(VHEAD, cgi.shWolf2, cs.eyecolor);
queuepoly(VHEAD, cgi.shWolf3, darkena(0x202020, 0, 0xFF));
}
else {
queuepoly(VHEAD, cgi.shPFace, fc(500, cs.skincolor, 1));
queuepoly(VHEAD1, (cs.charid&1) ? cgi.shFemaleHair : cgi.shPHead, fc(150, cs.haircolor, 2));
}
humanoid_eyes(V, cs.eyecolor, cs.skincolor);
#if CAP_COMPLEX2
if(camelot::knighted)
queuepoly(VBODY * VBS, id == pshRatling ? cgi.shRatCape1 : cgi.shKnightCloak, darkena(cloakcolor(camelot::knighted), 1, 0xFF));
#endif
if(tortoise::seek())
tortoise::draw(VBODY * VBS * ypush(-cgi.crossf*.25), tortoise::seekbits, 4, 0);
}
EX void drawPlayer(eMonster m, cell *where, const shiftmatrix& V, color_t col, double footphase, bool stop IS(false)) {
charstyle& cs = getcs();
#if CAP_COMPLEX2
auto& knighted = camelot::knighted;
#else
const bool knighted = false;
#endif
if(GDIM == 3) {
addradar(V, '@', cs.uicolor >> 8, 0xFF00FF00);
}
if(mapeditor::drawplayer && !mapeditor::drawUserShape(V, mapeditor::sgPlayer, cs.charid, cs.skincolor, where)) {
auto id = ePlayershape(cs.charid >> 1);
if(playershapes[id].is_animal) drawPlayer_animal(m, where, V, col, footphase, stop);
else if(playershapes[id].is_humanoid) drawPlayer_humanoid(m, where, V, col, footphase, stop);
if(cs.charid >= 10) {
else if(cs.charid >= 10) {
ShadowV(V, cgi.shSpaceship);
queuepoly(VBODY, cgi.shSpaceshipBase, fc(150, cs.skincolor, 4));
queuepoly(VBODY, cgi.shSpaceshipCockpit, fc(150, cs.eyecolor, 4));
@ -1354,186 +1601,6 @@ EX void drawPlayer(eMonster m, cell *where, const shiftmatrix& V, color_t col, d
queuepoly(VBODY * lmirror(), cgi.shSpaceshipGun, fc(150, cs.dresscolor, 4));
queuepoly(VBODY * lmirror(), cgi.shSpaceshipEngine, fc(150, cs.haircolor, 4));
}
else if(cs.charid >= 8) {
/* famililar */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VALEGS, cgi.shWolfLegs, fc(150, cs.dresscolor, 4));
}
else {
ShadowV(V, cgi.shWolfBody);
if(stop) return;
animallegs(VALEGS, moWolf, fc(500, cs.dresscolor, 4), footphase);
}
queuepoly(VABODY, cgi.shWolfBody, fc(0, cs.skincolor, 0));
queuepoly(VAHEAD, cgi.shFamiliarHead, fc(500, cs.haircolor, 2));
if(!shmup::on || shmup::curtime >= shmup::getPlayer()->nextshot) {
color_t col = items[itOrbDiscord] ? watercolor(0) : fc(314, cs.eyecolor, 3);
queuepoly(VAHEAD, cgi.shFamiliarEye, col);
queuepoly(VAHEAD * lmirror(), cgi.shFamiliarEye, col);
}
if(knighted)
queuepoly(VABODY, cgi.shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF));
if(tortoise::seek())
tortoise::draw(VABODY, tortoise::seekbits, 4, 0);
}
else if(cs.charid >= 6) {
/* dog */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VABODY, cgi.shDogBody, fc(0, cs.skincolor, 0));
}
else {
ShadowV(V, cgi.shDogTorso);
if(stop) return;
animallegs(VALEGS, moRunDog, fc(500, cs.dresscolor, 4), footphase);
queuepoly(VABODY, cgi.shDogTorso, fc(0, cs.skincolor, 0));
}
queuepoly(VAHEAD, cgi.shDogHead, fc(150, cs.haircolor, 2));
if(!shmup::on || shmup::curtime >= shmup::getPlayer()->nextshot) {
color_t col = items[itOrbDiscord] ? watercolor(0) : fc(314, cs.eyecolor, 3);
queuepoly(VAHEAD, cgi.shWolf1, col);
queuepoly(VAHEAD, cgi.shWolf2, col);
}
color_t colnose = items[itOrbDiscord] ? watercolor(0) : fc(314, 0xFF, 3);
queuepoly(VAHEAD, cgi.shWolf3, colnose);
if(knighted)
queuepoly(VABODY, cgi.shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF));
if(tortoise::seek())
tortoise::draw(VABODY, tortoise::seekbits, 4, 0);
}
else if(cs.charid >= 4) {
/* cat */
if(!mmspatial && !footphase) {
if(stop) return;
queuepoly(VALEGS, cgi.shCatLegs, fc(500, cs.dresscolor, 4));
}
else {
ShadowV(V, cgi.shCatBody);
if(stop) return;
animallegs(VALEGS, moRunDog, fc(500, cs.dresscolor, 4), footphase);
}
queuepoly(VABODY, cgi.shCatBody, fc(0, cs.skincolor, 0));
queuepoly(VAHEAD, cgi.shCatHead, fc(150, cs.haircolor, 2));
if(!shmup::on || shmup::curtime >= shmup::getPlayer()->nextshot) {
color_t col = items[itOrbDiscord] ? watercolor(0) : fc(314, cs.eyecolor, 3);
queuepoly(VAHEAD * xpush(.04), cgi.shWolf1, col);
queuepoly(VAHEAD * xpush(.04), cgi.shWolf2, col);
}
if(knighted)
queuepoly(VABODY, cgi.shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF));
if(tortoise::seek())
tortoise::draw(VABODY, tortoise::seekbits, 4, 0);
}
else {
/* human */
ShadowV(V, (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody);
if(stop) return;
const transmatrix VBS = otherbodyparts(V, fc(0, cs.skincolor, 0), items[itOrbFish] ? moWaterElemental : moPlayer, footphase);
queuepoly(VBODY * VBS, (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody, fc(0, cs.skincolor, 0));
if(cs.charid&1)
queuepoly(VBODY1 * VBS, cgi.shFemaleDress, fc(500, cs.dresscolor, 4));
if(cs.charid == 2)
queuepoly(VBODY2 * VBS, cgi.shPrinceDress, fc(400, cs.dresscolor, 5));
if(cs.charid == 3)
queuepoly(VBODY2 * VBS, cgi.shPrincessDress, fc(400, cs.dresscolor2, 5));
if(items[itOrbSide3])
queuepoly(VBODY * VBS, (cs.charid&1) ? cgi.shFerocityF : cgi.shFerocityM, fc(0, cs.skincolor, 0));
if(items[itOrbHorns]) {
queuepoly(VBODY * VBS, cgi.shBullHead, items[itOrbDiscord] ? watercolor(0) : 0xFF000030);
queuepoly(VBODY * VBS, cgi.shBullHorn, items[itOrbDiscord] ? watercolor(0) : 0xFF000040);
queuepoly(VBODY * VBS * lmirror(), cgi.shBullHorn, items[itOrbDiscord] ? watercolor(0) : 0xFF000040);
}
if(items[itOrbSide1] && !shmup::on)
queuepoly(VBODY * VBS * spin(-15._deg), cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, fc(314, cs.swordcolor, 3)); // 3 not colored
shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * lmirror() : VBODY * VBS;
if(peace::on) ;
else if(racing::on) {
#if CAP_RACING
if(racing::trophy[multi::cpid])
queuepoly(VWPN, cgi.shTrophy, racing::trophy[multi::cpid]);
#endif
}
else if(bow::crossbow_mode() && cs.charid < 4) {
queuepoly(VWPN, cgi.shCrossbow, fc(314, cs.bowcolor, 3));
int ti = items[itCrossbow];
if(shmup::on) {
ti = shmup::getPlayer()->nextshot - shmup::curtime;
if(ti <= 0) ti = 0;
else ti = 1 + ti / 500;
}
shiftmatrix VWPN1 = VWPN, VWPN2 = VWPN;
if(GDIM == 3) { ld h = cgi.human_height; VWPN1 = VWPN * lzpush(-h/60); VWPN2 = VWPN * lzpush(-h/30); }
if(ti <= 1) queuepoly(VWPN1, cgi.shCrossbowstringLoaded, fc(314, cs.bowcolor2, 3));
else if(ti <= 2) queuepoly(VWPN1, cgi.shCrossbowstringSemiloaded, fc(314, cs.bowcolor2, 3));
else queuepoly(VWPN1, cgi.shCrossbowstringUnloaded, fc(314, cs.bowcolor2, 3));
if(ti == 0) queuepoly(VWPN2, cgi.shCrossbowBolt, fc(314, cs.swordcolor, 3));
}
else if(items[itOrbThorns])
queuepoly(VWPN, cgi.shHedgehogBladePlayer, items[itOrbDiscord] ? watercolor(0) : 0x00FF00FF);
else if(!shmup::on && items[itOrbDiscord])
queuepoly(VWPN, cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, watercolor(0));
else if(items[itRevolver])
queuepoly(VWPN, cgi.shGunInHand, fc(314, cs.swordcolor, 3)); // 3 not colored
else if(items[itOrbSlaying]) {
queuepoly(VWPN, cgi.shFlailTrunk, fc(314, cs.swordcolor, 3));
queuepoly(VWPN, cgi.shHammerHead, fc(314, cs.swordcolor, 3));
}
else if(items[itCurseWeakness]) {
/* no weapon shown */
}
else if(!shmup::on)
queuepoly(VWPN, cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, fc(314, cs.swordcolor, 3)); // 3 not colored
else if(shmup::curtime >= shmup::getPlayer()->nextshot)
queuepoly(VWPN, cgi.shPKnife, fc(314, cs.swordcolor, 3)); // 3 not colored
if(items[itOrbBeauty]) {
if(cs.charid&1)
queuepoly(VHEAD1, cgi.shFlowerHair, darkena(iinf[itOrbBeauty].color, 0, 0xFF));
else
queuepoly(VWPN, cgi.shFlowerHand, darkena(iinf[itOrbBeauty].color, 0, 0xFF));
}
if(where && where->land == laWildWest) {
queuepoly(VHEAD1, cgi.shWestHat1, darkena(cs.swordcolor, 1, 0XFF));
queuepoly(VHEAD2, cgi.shWestHat2, darkena(cs.swordcolor, 0, 0XFF));
}
if(cheater && !autocheat) {
queuepoly(VHEAD1, (cs.charid&1) ? cgi.shGoatHead : cgi.shDemon, darkena(0xFFFF00, 0, 0xFF));
// queuepoly(V, shHood, darkena(0xFF00, 1, 0xFF));
}
else {
queuepoly(VHEAD, cgi.shPFace, fc(500, cs.skincolor, 1));
queuepoly(VHEAD1, (cs.charid&1) ? cgi.shFemaleHair : cgi.shPHead, fc(150, cs.haircolor, 2));
}
humanoid_eyes(V, cs.eyecolor, cs.skincolor);
if(knighted)
queuepoly(VBODY * VBS, cgi.shKnightCloak, darkena(cloakcolor(knighted), 1, 0xFF));
if(tortoise::seek())
tortoise::draw(VBODY * VBS * ypush(-cgi.crossf*.25), tortoise::seekbits, 4, 0);
}
}
}
@ -1710,7 +1777,7 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
return true;
case moBullet:
if(getcs().charid >= 10) {
if(getcs().charid/2 == pshSpaceship) {
ShadowV(V, cgi.shKnife);
queuepoly(VBODY, cgi.shMissile, getcs().swordcolor);
return true;
@ -1762,13 +1829,19 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
bool evil = !isPrincess(m);
int facecolor = evil ? 0xC0B090FF : 0xD0C080FF;
ShadowV(V, girl ? cgi.shFemaleBody : cgi.shPBody);
const transmatrix VBS = otherbodyparts(V, facecolor, !evil && items[itOrbFish] && items[itOrbEmpathy] ? moWaterElemental : m, footphase);
queuepoly(VBODY * VBS, girl ? cgi.shFemaleBody : cgi.shPBody, facecolor);
auto& cs = vid.cs;
auto id = ePlayershape(cs.charid >> 1);
auto& body = id == pshRatling ? cgi.shYeti : girl ? cgi.shFemaleBody : cgi.shPBody;
bool wears_dress = among(id, pshRogue, pshRatling);
ShadowV(V, body);
const transmatrix VBS = otherbodyparts(V, facecolor, !evil && items[itOrbFish] && items[itOrbEmpathy] ? moWaterElemental : id == pshRatling ? moYeti : m, footphase);
queuepoly(VBODY * VBS, body, facecolor);
if(m == moPrincessArmed)
queuepoly(VBODY * VBS * lmirror(), vid.cs.charid < 2 ? cgi.shSabre : cgi.shPSword, 0xFFFFFFFF);
queuepoly(VBODY * VBS * lmirror(), id == pshRogue ? cgi.shSabre : cgi.shPSword, 0xFFFFFFFF);
if((m == moFalsePrincess || m == moRoseBeauty) && where && where->cpdist == 1)
queuepoly(VBODY * VBS, cgi.shPKnife, 0xFFFFFFFF);
@ -1780,18 +1853,20 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
if(girl) {
queuepoly(VBODY1 * VBS, cgi.shFemaleDress, evil ? 0xC000C0FF : 0x00C000FF);
if(vid.cs.charid < 2)
if(wears_dress)
queuepoly(VBODY2 * VBS, cgi.shPrincessDress, (evil ? 0xC040C0C0 : 0x8080FFC0) | UNTRANS);
}
else {
if(vid.cs.charid < 2)
if(wears_dress)
queuepoly(VBODY1 * VBS, cgi.shPrinceDress, evil ? 0x802080FF : 0x404040FF);
}
auto& hair = id == pshRatling ? cgi.shRatHead : girl ? cgi.shFemaleHair : cgi.shPHead;
if(m == moRoseLady) {
// queuepoly(V, girl ? cgi.shGoatHead : cgi.shDemon, 0x800000FF);
// make her hair a bit darker to stand out in 3D
queuepoly(VHEAD1, girl ? cgi.shFemaleHair : cgi.shPHead, evil ? 0x500050FF : GDIM == 3 ? 0x666A64FF : 0x332A22FF);
queuepoly(VHEAD1, hair, evil ? 0x500050FF : GDIM == 3 ? 0x666A64FF : 0x332A22FF);
}
else if(m == moRoseBeauty) {
if(girl) {
@ -1805,10 +1880,14 @@ EX bool drawMonsterType(eMonster m, cell *where, const shiftmatrix& V1, color_t
}
}
else {
queuepoly(VHEAD1, girl ? cgi.shFemaleHair : cgi.shPHead,
evil ? 0xC00000FF : 0x332A22FF);
queuepoly(VHEAD1, hair, evil ? 0xC00000FF : 0x332A22FF);
}
queuepoly(VHEAD, cgi.shPFace, facecolor);
if(&hair == &cgi.shRatHead) {
queuepoly(VHEAD, cgi.shWolf1, 0x008000FF);
queuepoly(VHEAD, cgi.shWolf2, 0x008000FF);
queuepoly(VHEAD, cgi.shWolf3, darkena(0x202020, 0, 0xFF));
}
else queuepoly(VHEAD, cgi.shPFace, facecolor);
humanoid_eyes(V, evil ? 0x0000C0FF : 0x00C000FF, facecolor);
return true;
}
@ -6267,7 +6346,7 @@ EX void animateAttack(const movei& m, int layer) {
}
EX void animateCorrectAttack(const movei& m, int layer, eMonster who) {
if(among(who, moPlayer, moMimic, moIllusion, moShadow) && getcs().charid >= 10) {
if(among(who, moPlayer, moMimic, moIllusion, moShadow) && (getcs().charid/2) == pshSpaceship) {
animate_item_throw(m.s, m.t, itNone, moBullet);
return;
}
@ -6275,7 +6354,7 @@ EX void animateCorrectAttack(const movei& m, int layer, eMonster who) {
}
EX void animateHug(const movei& m, int layer) {
animateAttackOrHug(m, layer, 3, 0.5, -0.0713828 * cgi.scalefactor);
animateAttackOrHug(m, layer, 3, 0.5, ((getcs().charid/2) == pshRatling ? -0.15 : -0.0713828) * cgi.scalefactor);
}
vector<pair<cell*, animation> > animstack;

View File

@ -1586,6 +1586,12 @@ void geometry_information::prepare_shapes() {
bshape(shBugAntenna, PPR::MONSTER_BODY, scalefactor, 307);
bshape(shCatBody, PPR::MONSTER_BODY, scalefactor, 139);
bshape(shCatLegs, PPR::MONSTER_LEG, scalefactor, 140);
bshape(shBunnyBody, PPR::MONSTER_BODY, scalefactor, 434);
bshape(shBunnyHead, PPR::MONSTER_HEAD, scalefactor, 436);
bshape(shBunnyEar, PPR::MONSTER_HEAD, scalefactor, 437);
bshape(shBunnyTail, PPR::MONSTER_BODY, scalefactor, 438);
bshape(shFamiliarHead, PPR::MONSTER_HEAD, scalefactor, 141);
bshape(shFamiliarEye, PPR::MONSTER_EYE1, scalefactor, 142);
bshape(shCatHead, PPR::MONSTER_HEAD, scalefactor, 143);
@ -2560,6 +2566,18 @@ NEWSHAPE, 432, 1, 1, -0.0498532, 0.0220752, -0.0675516, 0.0261371, -0.0684933,
// shSpaceship
NEWSHAPE, 433, 1, 1, 0.0699706, 0, 0.0509304, 0.019032, 0.0056909, 0.023788, 0.0318813, 0.0309258, 0.0330715, 0.0368693, 0.00331668, 0.0380512, -0.0630665, 0.0699568, -0.0619577, 0.041535, -0.0678691, 0.0415233, -0.0678946, 0.0261072, -0.0572505, 0.0237463, -0.0572505, -0.0237463, -0.0678946, -0.0261072, -0.0678691, -0.0415233, -0.0619577, -0.041535, -0.0630665, -0.0699568, 0.00331668, -0.0380512, 0.0330715, -0.0368693, 0.0318813, -0.0309258, 0.0056909, -0.023788, 0.0509304, -0.019032,
// shBunnyBody
NEWSHAPE, 434, 1, 2, -0.182836, 0.00134439, -0.166475, 0.00939776, -0.184217, 0.0174805, -0.166723, 0.024617, -0.17245, 0.042553, -0.157684, 0.035786, -0.164538, 0.051488, -0.14867, 0.046949, -0.155517, 0.061536, -0.140794, 0.054753, -0.141981, 0.068196, -0.125033, 0.058051, -0.125087, 0.071478, -0.112675, 0.059126, -0.113871, 0.078147, -0.099238, 0.065787, -0.09929, 0.080325, -0.089161, 0.065756, -0.086969, 0.080279, -0.080217, 0.066848, -0.07356, 0.083591, -0.06347, 0.067924, -0.055703, 0.086897, -0.048978, 0.070128, -0.045663, 0.085757, -0.036721, 0.067879, -0.028944, 0.082379, -0.024473, 0.063406, -0.016698, 0.085718, -0.012236, 0.066743, -0.001113, 0.080128, 0.005561, 0.062283, 0.014465, 0.073436, 0.017795, 0.058945, 0.026707, 0.073445, 0.030032, 0.057839, 0.042293, 0.070117, 0.044501, 0.055626, 0.053427, 0.064557, 0.054515, 0.046727, 0.072375, 0.056786, 0.070112, 0.038951, 0.082394, 0.040084, 0.070104, 0.03227, 0.077909, 0.026712, 0.075671, 0.020031, 0.089069, 0.014474, 0.075666, 0.011127, 0.085713, 0.005566, 0.077896, -0.001113,
// shBunnyHead
NEWSHAPE, 436, 1, 2, 0.073175, 0, 0.058843, 0.007699, 0.07428, 0.010454, 0.062705, 0.019251, 0.077045, 0.019811, 0.068229, 0.032464, 0.084236, 0.031933, 0.077073, 0.043491, 0.091431, 0.037454, 0.098645, 0.047394, 0.108865, 0.0406363, 0.121029, 0.0547394, 0.125041, 0.0426847, 0.141797, 0.0512883, 0.136185, 0.0422124, 0.157048, 0.0488258, 0.147348, 0.0397287, 0.167717, 0.041514, 0.160393, 0.029313, 0.171614, 0.030448, 0.164858, 0.020469, 0.171594, 0.021588, 0.174963, 0.020486, 0.178894, 0.017169, 0.181703, 0.013295, 0.183949, 0.005541,
// shBunnyEar
NEWSHAPE, 437, 1, 1, 0.0826431, 0.0110191, 0.0685843, 0.0150185, 0.0575504, 0.0140123, 0.0535413, 0.0150116, 0.0425239, 0.0210118, 0.0325139, 0.0255109, 0.0210093, 0.0365162, 0.0205116, 0.0430244, 0.0190131, 0.0490339, 0.040542, 0.0500518, 0.0766509, 0.0450888, 0.0871982, 0.0390888, 0.0992563, 0.0230596, 0.101266, 0.0175461, 0.0856591, 0.0110205,
// shBunnyTail
NEWSHAPE, 438, 1, 2, -0.146275, -0.00452397, -0.135622, -0.0105484, -0.149835, -0.0100561, -0.145778, -0.0180966, -0.158996, -0.0100631, -0.159013, -0.0231475, -0.164607, -0.013088, -0.187654, -0.0257267, -0.184047, -0.0176483, -0.195877, -0.0267564, -0.195345, -0.0186764, -0.205659, -0.0242546, -0.203064, -0.0161643, -0.21598, -0.0187149, -0.20873, -0.00960259, -0.221145, -0.0101211, -0.21441, -0.00455116, -0.224251, -0.000506209,
NEWSHAPE, NEWSHAPE
};