mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-10-31 22:12:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			806 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			806 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Hyperbolic Rogue -- player/mimic graphics file
 | |
| // Copyright (C) 2011-2025 Zeno Rogue, see 'hyper.cpp' for details
 | |
| 
 | |
| #include "hyper.h"
 | |
| namespace hr {
 | |
| 
 | |
| EX int lightat, safetyat;
 | |
| EX void drawLightning() { lightat = ticks; }
 | |
| EX void drawSafety() { safetyat = ticks; }
 | |
| 
 | |
| EX void drawShield(const shiftmatrix& V, eItem it) {
 | |
| #if CAP_CURVE
 | |
|   float ds = ptick(300);
 | |
|   color_t col = iinf[it].color;
 | |
|   if(it == itOrbShield && items[itOrbTime] && !orbused[it])
 | |
|     col = (col & 0xFEFEFE) / 2;
 | |
|   if(sphere && cwt.at->land == laHalloween && !wmblack && !wmascii)
 | |
|     col = 0;
 | |
|   double d = it == itOrbShield ? cgi.hexf : cgi.hexf - .1;
 | |
|   int mt = sphere ? 7 : 5;
 | |
| #if MAXMDIM >= 4
 | |
|   if(GDIM == 3)
 | |
|     queueball(V * lzpush(cgi.GROIN1), cgi.human_height / 2, darkena(col, 0, 0xFF), itOrbShield);
 | |
| #else
 | |
|   if(1) ;
 | |
| #endif  
 | |
|   else {
 | |
|     for(ld a=0; a<=cgi.S84*mt+1e-6; a+=pow(.5, vid.linequality))
 | |
|       curvepoint(xspinpush0(a * cgi.S_step, d + sin(ds + 90._deg*a/mt)*.1));
 | |
|     queuecurve(V, darkena(col, 0, 0xFF), 0x8080808, PPR::LINE);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawSpeed(const shiftmatrix& V, ld scale IS(1)) {
 | |
| #if CAP_CURVE
 | |
|   ld ds = ptick(10);
 | |
|   color_t col = darkena(iinf[itOrbSpeed].color, 0, 0xFF);
 | |
| #if MAXMDIM >= 4
 | |
|   if(GDIM == 3) queueball(V * lzpush(cgi.GROIN1), cgi.human_height * 0.55, col, itOrbSpeed);
 | |
|   else
 | |
| #endif
 | |
|   for(int b=0; b<cgi.S84; b+=cgi.S14) {
 | |
|     PRING(a)
 | |
|       curvepoint(xspinpush0((ds+b+a) * cgi.S_step, cgi.hexf*a/cgi.S84*scale));
 | |
|     queuecurve(V, col, 0x8080808, PPR::LINE);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawSafety(const shiftmatrix& V, int ct) {
 | |
|   if(inHighQual) return;
 | |
| #if CAP_QUEUE
 | |
|   ld ds = ptick(50);
 | |
|   color_t col = darkena(iinf[itOrbSafety].color, 0, 0xFF);
 | |
|   #if MAXMDIM >= 4
 | |
|   if(GDIM == 3) {
 | |
|     queueball(V * lzpush(cgi.GROIN1), 2*cgi.hexf, col, itOrbSafety);
 | |
|     return;
 | |
|     }
 | |
|   #endif
 | |
|   for(int a=0; a<ct; a++)
 | |
|     queueline(V*xspinpush0((ds+a*cgi.S84/ct) * cgi.S_step, 2*cgi.hexf), V*xspinpush0((ds+(a+(ct-1)/2)*cgi.S84/ct) * cgi.S_step, 2*cgi.hexf), col, vid.linequality);
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawFlash(const shiftmatrix& V) {
 | |
| #if CAP_CURVE
 | |
|   float ds = ptick(300);
 | |
|   color_t col = darkena(iinf[itOrbFlash].color, 0, 0xFF);
 | |
|   col &= ~1;
 | |
|   for(int u=0; u<5; u++) {
 | |
|     ld rad = cgi.hexf * (2.5 + .5 * sin(ds+u*.3));
 | |
|     #if MAXMDIM >= 4
 | |
|     if(GDIM == 3) {
 | |
|       queueball(V * lzpush(cgi.GROIN1), rad, col, itOrbFlash);
 | |
|       }
 | |
|     #else
 | |
|     if(1) ;
 | |
|     #endif
 | |
|     else {
 | |
|       PRING(a) curvepoint(xspinpush0(a * cgi.S_step, rad));
 | |
|       queuecurve(V, col, 0x8080808, PPR::LINE);
 | |
|       }
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawLove(const shiftmatrix& V, int hdir) {
 | |
| #if CAP_CURVE
 | |
|   float ds = ptick(300);
 | |
|   color_t col = darkena(iinf[itOrbLove].color, 0, 0xFF);
 | |
|   col &= ~1;
 | |
|   for(int u=0; u<5; u++) {
 | |
|     shiftmatrix V1 = chei(V, u, 5);
 | |
|     PRING(a) {
 | |
|       double d = (1 + cos(a * cgi.S_step)) / 2;
 | |
|       double z = a; if(z>cgi.S42) z = cgi.S84-z;
 | |
|       if(z <= 10) d += (10-z) * (10-z) * (10-z) / 3000.;
 | |
| 
 | |
|       ld rad = cgi.hexf * (2.5 + .5 * sin(ds+u*.3)) * d;
 | |
|       curvepoint(xspinpush0((cgi.S42+hdir+a-1) * cgi.S_step, rad));
 | |
|       }
 | |
|     queuecurve(V1, col, 0x8080808, PPR::LINE);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawWinter(const shiftmatrix& V, ld hdir, color_t col) {
 | |
| #if CAP_QUEUE
 | |
|   float ds = ptick(300);
 | |
|   col = darkena(col, 0, 0xFF);
 | |
|   for(int u=0; u<20; u++) {
 | |
|     ld rad = sin(ds+u * TAU / 20) * M_PI / S7;
 | |
|     shiftmatrix V1 = chei(V, u, 20);
 | |
|     queueline(V1*xspinpush0(M_PI+hdir+rad, cgi.hexf*.5), V1*xspinpush0(M_PI+hdir+rad, cgi.hexf*3), col, 2 + vid.linequality);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawLightning(const shiftmatrix& V) {
 | |
| #if CAP_QUEUE
 | |
|   float ds = ptick(600);
 | |
|   color_t col = darkena(iinf[itOrbLightning].color, 0, 0xFF);
 | |
|   for(int u=0; u<20; u++) {
 | |
|     ld leng, rad;
 | |
|     if(vid.flasheffects) {
 | |
|       leng = 0.5 / (0.1 + (rand() % 100) / 100.0);
 | |
|       rad = rand() % 1000;
 | |
|       }
 | |
|     else {
 | |
|       if(u % 5) leng = 1.25 + sintick(200, ld(u) * 1.25) * 0.25;
 | |
|       else leng = 2 + sintick(200, ld(u) * 1.25);
 | |
|       rad = (u + ds) * TAU / 20;
 | |
|       }
 | |
|     shiftmatrix V1 = chei(V, u, 20);
 | |
|     queueline(V1*xspinpush0(rad, cgi.hexf*0.3), V1*xspinpush0(rad, cgi.hexf*leng), col, 2 + vid.linequality);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawCurse(const shiftmatrix& V, eItem it) {
 | |
| #if CAP_QUEUE
 | |
|   float ds = ptick(450) + (int(it) * 5.5); // Extra offset so both Gluttony and Repulsion are easily visible
 | |
|   color_t col = darkena(iinf[it].color, 0, 0xFF);
 | |
|   for(int u=0; u<20; u++) {
 | |
|     ld leng, rad;
 | |
|     if(vid.flasheffects) {
 | |
|       leng = 0.6 + 0.3 * randd();
 | |
|       rad = rand() % 1000;
 | |
|       }
 | |
|     else {
 | |
|       leng = 0.85 + sintick(150, ld(u) * 1.25) * 0.15;
 | |
|       rad = (u + ds) * TAU / 20;
 | |
|       }
 | |
|     shiftmatrix V1 = chei(V, u, 20);
 | |
|     queueline(V1*xspinpush0(rad, cgi.hexf*0.3), V1*xspinpush0(rad, cgi.hexf*leng), col, 2 + vid.linequality);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
| 
 | |
| EX void drawPlayerEffects(const shiftmatrix& V, const shiftmatrix& Vparam, cell *c, eMonster m) {
 | |
|   bool onplayer = m == moPlayer;
 | |
|   if(!onplayer && !items[itOrbEmpathy]) return;
 | |
|   if(items[itOrbShield] > (shmup::on ? 0 : ORBBASE)) drawShield(V, itOrbShield);
 | |
|   if(items[itOrbShell] > (shmup::on ? 0 : ORBBASE)) drawShield(V, itOrbShell);
 | |
| 
 | |
|   if(items[itOrbSpeed]) drawSpeed(V, (items[itOrbSpeed] % 2) ? 1.1 : 0.8);
 | |
|   if(items[itCurseGluttony]) drawCurse(V, itCurseGluttony); 
 | |
|   if(items[itCurseRepulsion]) drawCurse(V, itCurseRepulsion); 
 | |
| 
 | |
|   if(onplayer && (items[itOrbSword] || items[itOrbSword2])) {
 | |
|     using namespace sword;
 | |
|   
 | |
|     if(shmup::on && SWORDDIM == 2) {
 | |
| #if CAP_SHAPES
 | |
|       if(items[itOrbSword])
 | |
|         queuepoly(V*spin(shmup::pc[multi::cpid]->swordangle), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0xC0 + 0x30 * sintick(200)));
 | |
|   
 | |
|       if(items[itOrbSword2])
 | |
|         queuepoly(V*spin(shmup::pc[multi::cpid]->swordangle+M_PI), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword2].color, 0, 0xC0 + 0x30 * sintick(200)));
 | |
| #endif
 | |
|       }                  
 | |
| 
 | |
|     else if(SWORDDIM == 3) {
 | |
| #if CAP_SHAPES
 | |
|       shiftmatrix Vsword = 
 | |
|         shmup::on ? V * shmup::swordmatrix[multi::cpid] * cspin90(2, 0)
 | |
|                   : Vparam * rgpushxto0(inverse_shift(gmatrix[c], tC0(V))) * sword::dir[multi::cpid].T;
 | |
| 
 | |
|       if(items[itOrbSword])
 | |
|         queuepoly(Vsword * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0xC0 + 0x30 * sintick(200)));
 | |
|   
 | |
|       if(items[itOrbSword2])
 | |
|         queuepoly(Vsword * lpispin() * cspin(1,2, ticks / 150.), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword2].color, 0, 0xC0 + 0x30 * sintick(200)));
 | |
| #endif
 | |
|       }
 | |
|     
 | |
|     else {
 | |
|       int& ang = sword::dir[multi::cpid].angle;
 | |
|       ang %= sword::sword_angles;
 | |
| 
 | |
| #if CAP_QUEUE || CAP_SHAPES
 | |
|       shiftmatrix Vnow = Vparam * rgpushxto0(inverse_shift(Vparam, tC0(V))) * ddspin180(c,0);
 | |
| #endif
 | |
| 
 | |
|       int adj = 1 - ((sword_angles/cwt.at->type)&1);
 | |
|       
 | |
| #if CAP_QUEUE
 | |
|       if(!euclid && !mhybrid) for(int a=0; a<sword_angles; a++) {
 | |
|         if(a == ang && items[itOrbSword]) continue;
 | |
|         if((a+sword_angles/2)%sword_angles == ang && items[itOrbSword2]) continue;
 | |
|         bool longer = sword::pos2(cwt.at, a-1) != sword::pos2(cwt.at, a+1);
 | |
|         if(sword_angles > 48 && !longer) continue;
 | |
|         color_t col = darkena(0xC0C0C0, 0, 0xFF);
 | |
|         ld l0 = PURE ? 0.6 * cgi.scalefactor : longer ? 0.36 : 0.4;
 | |
|         ld l1 = PURE ? 0.7 * cgi.scalefactor : longer ? 0.44 : 0.42;
 | |
| #if MAXMDIM >= 4
 | |
|         hyperpoint h0 = GDIM == 3 ? xpush(l0) * lzpush(cgi.FLOOR - cgi.human_height/50) * C0 : xpush0(l0);
 | |
|         hyperpoint h1 = GDIM == 3 ? xpush(l1) * lzpush(cgi.FLOOR - cgi.human_height/50) * C0 : xpush0(l1);
 | |
| #else
 | |
|         hyperpoint h0 = xpush0(l0);
 | |
|         hyperpoint h1 = xpush0(l1);
 | |
| #endif
 | |
|         shiftmatrix T = Vnow*spin((sword_angles + (-adj-2*a)) * M_PI / sword_angles);
 | |
|         queueline(T*h0, T*h1, col, 1, PPR::SUPERLINE);
 | |
|         }
 | |
| #endif
 | |
| 
 | |
| #if CAP_SHAPES
 | |
|       if(items[itOrbSword])
 | |
|         queuepoly(Vnow*spin(M_PI+(-adj-2*ang)*M_PI/sword_angles), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword].color, 0, 0x80 + 0x70 * sintick(200)));
 | |
|   
 | |
|       if(items[itOrbSword2])
 | |
|         queuepoly(Vnow*spin((-adj-2*ang)*M_PI/sword_angles), (peace::on ? cgi.shMagicShovel : cgi.shMagicSword), darkena(iinf[itOrbSword2].color, 0, 0x80 + 0x70 * sintick(200)));
 | |
| #endif
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   if(onplayer && items[itOrbSafety]) drawSafety(V, c->type);
 | |
| 
 | |
|   if(onplayer && items[itOrbFlash]) drawFlash(V); 
 | |
|   if(onplayer && items[itOrbLove]) drawLove(V, 0); // displaydir(c, cwt.spin)); 
 | |
| 
 | |
|   if(items[itOrbWinter]) 
 | |
|     drawWinter(V, 0, iinf[itOrbWinter].color); // displaydir(c, cwt.spin));
 | |
| 
 | |
|   if(items[itOrbFire]) 
 | |
|     drawWinter(V, 0, iinf[itOrbFire].color); // displaydir(c, cwt.spin));
 | |
| 
 | |
|   if(items[itCurseWater]) 
 | |
|     drawWinter(V, 0, iinf[itCurseWater].color); // displaydir(c, cwt.spin));
 | |
|   
 | |
|   if(onplayer && items[itOrbLightning]) drawLightning(V);
 | |
|   
 | |
|   if(safetyat > 0) {
 | |
|     int tim = ticks - safetyat;
 | |
|     if(tim > 2500) safetyat = 0;
 | |
|     for(int u=tim; u<=2500; u++) {
 | |
|       if((u-tim)%250) continue;
 | |
|       ld rad = cgi.hexf * u / 250;
 | |
|       color_t col = darkena(iinf[itOrbSafety].color, 0, 0xFF);
 | |
|       PRING(a)
 | |
|         curvepoint(xspinpush0(a * cgi.S_step, rad));
 | |
|       queuecurve(V, col, 0, PPR::LINE);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| #if HDR
 | |
| struct playershape {
 | |
|   string name;
 | |
|   bool is_humanoid;
 | |
|   bool is_animal;
 | |
|   };
 | |
| 
 | |
| enum ePlayershape { pshRogue, pshPrincess, pshCat, pshDog, pshFamiliar, pshSpaceship, pshBunny, pshRatling, pshHyperbug, pshSkeleton, 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},
 | |
|   {"hyperbug", false, true},
 | |
|   {"Skeleton", 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 == pshHyperbug) {
 | |
|     ShadowV(V, cgi.shBugBody);
 | |
|     if(!mmspatial && !footphase)
 | |
|       queuepoly(VABODY, cgi.shBugBody, fc(0, cs.skincolor, 0));
 | |
|     else {
 | |
|       animallegs(VALEGS, moBug0, fc(500, cs.dresscolor, 4), footphase);
 | |
|       queuepoly(VABODY, cgi.shBugAntenna, fc(150, cs.skincolor, 2));
 | |
|       }
 | |
|     queuepoly(VABODY, cgi.shBugArmor, fc(400, cs.haircolor, 5));
 | |
|     }
 | |
| 
 | |
|   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 : (id == pshSkeleton) ? cgi.shSkeletonBody : (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody;
 | |
| 
 | |
|   ShadowV(V, body);
 | |
|   if(stop) return;
 | |
| 
 | |
|   const transmatrix VBS = otherbodyparts(V, fc(0, (id == pshRatling || id == pshSkeleton) ? cs.dresscolor : cs.skincolor, 0), items[itOrbFish] ? moWaterElemental : moPlayer, footphase);
 | |
| 
 | |
| 
 | |
|   queuepoly(VBODY * VBS, body, fc(0, cs.skincolor, 0));
 | |
| 
 | |
|   if(id == pshRatling) queuepoly(VLEG, cgi.shRatTail, fc(100, cs.dresscolor2, 5));
 | |
| 
 | |
|   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(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(!shmup::on && items[itOrbDiscord])
 | |
|     queuepoly(VWPN, cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, watercolor(0));
 | |
|   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 if(id == pshSkeleton) {
 | |
|     if(GDIM == 2) queuepoly(VHEAD, cgi.shSkull, fc(500, cs.haircolor, 1));
 | |
|     if(GDIM == 2) queuepoly(VHEAD1, cgi.shSkullEyes, 0x000000FF);
 | |
|     }
 | |
|   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(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);
 | |
|   
 | |
|     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));
 | |
|       queuepoly(VBODY, cgi.shSpaceshipGun, fc(150, cs.dresscolor, 4));
 | |
|       queuepoly(VBODY, cgi.shSpaceshipEngine, fc(150, cs.haircolor, 4));
 | |
|       queuepoly(VBODY * lmirror(), cgi.shSpaceshipGun, fc(150, cs.dresscolor, 4));
 | |
|       queuepoly(VBODY * lmirror(), cgi.shSpaceshipEngine, fc(150, cs.haircolor, 4));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| EX void drawMimic(eMonster m, cell *where, const shiftmatrix& V, color_t col, double footphase) {
 | |
|   charstyle& cs = getcs();
 | |
|   auto id = ePlayershape(cs.charid >> 1);
 | |
|   
 | |
|   if(mapeditor::drawUserShape(V, mapeditor::sgPlayer, cs.charid, darkena(col, 0, 0x80), where)) return;
 | |
|   
 | |
|   if(id == pshSpaceship) {
 | |
|     ShadowV(V, cgi.shSpaceship);
 | |
|     queuepoly(VBODY, cgi.shSpaceshipBase, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VBODY, cgi.shSpaceshipCockpit, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VBODY, cgi.shSpaceshipGun, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VBODY, cgi.shSpaceshipEngine, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VBODY * lmirror(), cgi.shSpaceshipGun, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VBODY * lmirror(), cgi.shSpaceshipEngine, darkena(col, 0, 0xC0));
 | |
|     }
 | |
|   else if(id == pshFamiliar) {
 | |
|     queuepoly(VABODY, cgi.shWolfBody, darkena(col, 0, 0xC0));
 | |
|     ShadowV(V, cgi.shWolfBody);
 | |
| 
 | |
|     if(mmspatial || footphase)
 | |
|       animallegs(VALEGS, moWolf, darkena(col, 0, 0xC0), footphase);
 | |
|     else 
 | |
|       queuepoly(VABODY, cgi.shWolfLegs, darkena(col, 0, 0xC0));
 | |
| 
 | |
|     queuepoly(VABODY, cgi.shFamiliarHead, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VAHEAD, cgi.shFamiliarEye, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VAHEAD * lmirror(), cgi.shFamiliarEye, darkena(col, 0, 0xC0));
 | |
|     }
 | |
|   else if(id == pshDog) {
 | |
|     ShadowV(V, cgi.shDogBody);
 | |
|     queuepoly(VAHEAD, cgi.shDogHead, darkena(col, 0, 0xC0));
 | |
|     if(mmspatial || footphase) {
 | |
|       animallegs(VALEGS, moRunDog, darkena(col, 0, 0xC0), footphase);
 | |
|       queuepoly(VABODY, cgi.shDogTorso, darkena(col, 0, 0xC0));
 | |
|       }
 | |
|     else 
 | |
|       queuepoly(VABODY, cgi.shDogBody, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VABODY, cgi.shWolf1, darkena(col, 1, 0xC0));
 | |
|     queuepoly(VABODY, cgi.shWolf2, darkena(col, 1, 0xC0));
 | |
|     queuepoly(VABODY, cgi.shWolf3, darkena(col, 1, 0xC0));
 | |
|     }
 | |
|   else if(id == pshBunny) {
 | |
|     ShadowV(V, cgi.shBunnyBody);
 | |
|     queuepoly(VAHEAD, cgi.shBunnyHead, darkena(col, 0, 0xC0));
 | |
|     if(mmspatial || footphase) {
 | |
|       animallegs(VALEGS, moRunDog, darkena(col, 0, 0xC0), footphase);
 | |
|       queuepoly(VABODY, cgi.shBunnyBody, darkena(col, 0, 0xC0));
 | |
|       }
 | |
|     else
 | |
|       queuepoly(VABODY, cgi.shBunnyBody, darkena(col, 0, 0xC0));
 | |
| 
 | |
|     queuepoly(VABODY, cgi.shBunnyTail, darkena(col, 1, 0xC0));
 | |
|     queuepoly(VABODY, cgi.shBunnyHead, darkena(col, 1, 0xC0));
 | |
| 
 | |
|     queuepoly(VAHEAD * xpush(.04), cgi.shWolf1, col);
 | |
|     queuepoly(VAHEAD * xpush(.04), cgi.shWolf2, col);
 | |
| 
 | |
|     queuepoly(VAHEAD, cgi.shBunnyEar, darkena(col, 1, 0x80));
 | |
|     queuepoly(VAHEAD * MirrorY, cgi.shBunnyEar, darkena(col, 2, 0x80));
 | |
|     }
 | |
|   else if(id == pshHyperbug) {
 | |
|     ShadowV(V, cgi.shBugBody);
 | |
|     if(!mmspatial && !footphase)
 | |
|       queuepoly(VABODY, cgi.shBugBody, darkena(col, 0, 0xC0));
 | |
|     else {
 | |
|       animallegs(VALEGS, moBug0, darkena(col, 0, 0xC0), footphase);
 | |
|       queuepoly(VABODY, cgi.shBugAntenna, darkena(col, 0, 0xC0));
 | |
|       }
 | |
|     queuepoly(VABODY, cgi.shBugArmor, darkena(col, 0, 0xC0));
 | |
|     }
 | |
|   else if(id == pshCat) {
 | |
|     ShadowV(V, cgi.shCatBody);
 | |
|     queuepoly(VABODY, cgi.shCatBody, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VAHEAD, cgi.shCatHead, darkena(col, 0, 0xC0));
 | |
|     if(mmspatial || footphase) 
 | |
|       animallegs(VALEGS, moRunDog, darkena(col, 0, 0xC0), footphase);
 | |
|     else 
 | |
|       queuepoly(VALEGS, cgi.shCatLegs, darkena(col, 0, 0xC0));
 | |
|     queuepoly(VAHEAD * xpush(.04), cgi.shWolf1, darkena(col, 1, 0xC0));
 | |
|     queuepoly(VAHEAD * xpush(.04), cgi.shWolf2, darkena(col, 1, 0xC0));
 | |
|     }
 | |
|   else {
 | |
|     const transmatrix VBS = otherbodyparts(V, darkena(col, 0, 0x40), m, footphase);
 | |
|     auto& body = (id == pshRatling) ? cgi.shYeti : (id == pshSkeleton) ? cgi.shSkeletonBody : (cs.charid&1) ? cgi.shFemaleBody : cgi.shPBody;
 | |
|     queuepoly(VBODY * VBS, body,  darkena(col, 0, 0X80));
 | |
| 
 | |
|     if(bow::crossbow_mode() && cs.charid < 4) {
 | |
|       shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * lmirror() : VBODY * VBS;
 | |
|       color_t col1 = darkena(col, 0, 0x40);
 | |
|       queuepoly(VWPN, cgi.shCrossbow, col1);
 | |
|       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, col1);
 | |
|       else if(ti <= 2) queuepoly(VWPN1, cgi.shCrossbowstringSemiloaded, col1);
 | |
|       else queuepoly(VWPN1, cgi.shCrossbowstringUnloaded, col1);
 | |
|       if(ti == 0) queuepoly(VWPN2, cgi.shCrossbowBolt, col1);
 | |
|       }
 | |
|     else if(!shmup::on) {
 | |
|       bool emp = items[itOrbEmpathy] && m != moShadow;
 | |
|       if(items[itOrbThorns] && emp)
 | |
|         queuepoly(VBODY * VBS, cgi.shHedgehogBladePlayer, darkena(col, 0, 0x40));
 | |
|       if(items[itOrbSide1] && !shmup::on)
 | |
|         queuepoly(VBODY * VBS * spin(-15._deg), cs.charid >= 2 ? cgi.shSabre : cgi.shPSword, darkena(col, 0, 0x40));
 | |
|       if(items[itOrbSide3] && emp)
 | |
|         queuepoly(VBODY * VBS, (cs.charid&1) ? cgi.shFerocityF : cgi.shFerocityM, darkena(col, 0, 0x40));
 | |
| 
 | |
|       shiftmatrix VWPN = cs.lefthanded ? VBODY * VBS * lmirror() : VBODY * VBS;
 | |
|       queuepoly(VWPN, (cs.charid >= 2 ? cgi.shSabre : cgi.shPSword), darkena(col, 0, 0XC0));
 | |
|       }
 | |
|     else if(!where || shmup::curtime >= shmup::getPlayer()->nextshot)
 | |
|       queuepoly(VBODY * VBS, cgi.shPKnife, darkena(col, 0, 0XC0));
 | |
| 
 | |
|     #if CAP_COMPLEX2
 | |
|     if(camelot::knighted)
 | |
|       queuepoly(VBODY3 * VBS, cgi.shKnightCloak, darkena(col, 1, 0xC0));
 | |
|     #endif
 | |
| 
 | |
|     if(&body == &cgi.shYeti) {
 | |
|       queuepoly(VHEAD1, cgi.shRatHead,  darkena(col, 1, 0xC0));
 | |
|       queuepoly(VHEAD, cgi.shWolf1, darkena(col, 2, 0xC0));
 | |
|       queuepoly(VHEAD, cgi.shWolf2, darkena(col, 2, 0xC0));
 | |
|       queuepoly(VHEAD, cgi.shWolf3, darkena(col, 2, 0xC0));
 | |
|       }
 | |
|     else if(&body == &cgi.shSkeletonBody) {
 | |
|       queuepoly(VHEAD1, cgi.shSkull,  darkena(col, 1, 0xC0));
 | |
|       queuepoly(VHEAD, cgi.shSkullEyes, darkena(col, 2, 0xC0));
 | |
|       }
 | |
|     else {
 | |
|       queuepoly(VHEAD1, (cs.charid&1) ? cgi.shFemaleHair : cgi.shPHead,  darkena(col, 1, 0XC0));
 | |
|       queuepoly(VHEAD, cgi.shPFace,  darkena(col, 0, 0XC0));
 | |
|       }
 | |
|     if(cs.charid&1)
 | |
|       queuepoly(VBODY1 * VBS, cgi.shFemaleDress,  darkena(col, 1, 0XC0));
 | |
|     if(cs.charid == 2)
 | |
|       queuepoly(VBODY2 * VBS, cgi.shPrinceDress,  darkena(col, 1, 0XC0));
 | |
|     if(cs.charid == 3)
 | |
|       queuepoly(VBODY2 * VBS, cgi.shPrincessDress,  darkena(col, 1, 0XC0));
 | |
|     if(id == pshRatling) queuepoly(VLEG, cgi.shRatTail, darkena(col, 1, 0xC0));
 | |
| 
 | |
|     humanoid_eyes(V,  0xFF, darkena(col, 0, 0x40));
 | |
|     }
 | |
|   }
 | |
| 
 | |
| EX void draw_movement_arrows(cell *c, const transmatrix& V, int df) {
 | |
| 
 | |
|   if(viewdists) return;
 | |
|   
 | |
|   string keylist = "";
 | |
|   const ld keysize = .6;      
 | |
| 
 | |
|   color_t col = getcs().uicolor;
 | |
| 
 | |
|   for(int d=0; d<8; d++) {
 | |
|   
 | |
|     movedir md = vectodir(spin(-d * 45._deg) * smalltangent());
 | |
|     cellwalker xc = cwt + md.d;
 | |
|     if(xc.spin != df) continue;
 | |
|     xc += wstep;
 | |
|     if(xc.at == c) {
 | |
|       transmatrix fixrot = sphereflip * rgpushxto0(sphereflip * tC0(V));
 | |
|       // make it more transparent
 | |
|       col -= (col & 0xFF) >> 1;
 | |
|       poly_outline = OUTLINE_DEFAULT;
 | |
|       
 | |
|       char key = 0;
 | |
|       if(vid.axes >= 5)
 | |
|         key = (vid.axes == 5 ? keys_wasd : keys_vi)[d];
 | |
|       
 | |
|       if(vid.axes >= 5) keylist += key;
 | |
|       else
 | |
|         queuepoly(shiftless(fixrot * spin(-d * 45._deg)), cgi.shArrow, col);
 | |
| 
 | |
|       if((c->type & 1) && (isStunnable(c->monst) || isPushable(c->wall))) {
 | |
|         transmatrix Centered = rgpushxto0(unshift(tC0(cwtV)));
 | |
|         int sd = md.subdir;
 | |
|         if(keybd_subdir_enabled) sd = keybd_subdir;
 | |
| 
 | |
|         transmatrix T = iso_inverse(Centered) * rgpushxto0(Centered * tC0(V)) * lrspintox(Centered*tC0(V)) * spin(-sd * M_PI/S7) * xpush(0.2);
 | |
|         
 | |
|         if(vid.axes >= 5)
 | |
|           queuestr(shiftless(T), keysize * mapfontscale / 100, s0 + key, col >> 8, 1);
 | |
|         
 | |
|         else
 | |
|           queuepoly(shiftless(T), cgi.shArrow, col);
 | |
|         }
 | |
|       else if(!confusingGeometry()) break;
 | |
|       }
 | |
|     }
 | |
|   if(keylist != "") queuestr(shiftless(V), keysize * mapfontscale / 100, keylist, col >> 8, 1);
 | |
|   }
 | |
| 
 | |
| EX void drawmovestar(double dx, double dy) {
 | |
| 
 | |
|   DEBBI(DF_GRAPH, ("draw movestar"));
 | |
|   if(viewdists) return;
 | |
|   if(GDIM == 3) return;
 | |
| 
 | |
|   if(!playerfound) return;
 | |
|   
 | |
|   if(shmup::on) return;
 | |
| #if CAP_RUG
 | |
|   if(rug::rugged && multi::players == 1 && !multi::alwaysuse) return;
 | |
| #endif
 | |
| 
 | |
|   shiftpoint H = cwtV * tile_center();
 | |
|   ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
 | |
|   shiftmatrix Centered;
 | |
| 
 | |
|   if(euclid) 
 | |
|     Centered = shiftless(eupush(H.h));
 | |
|   else if(R > 1e-9) Centered = rgpushxto0(H);
 | |
|   else Centered = shiftless(Id);
 | |
|   
 | |
|   Centered = Centered * rgpushxto0(hpxy(dx*5, dy*5));
 | |
|   if(multi::cpid >= 0) multi::crosscenter[multi::cpid] = Centered;
 | |
|   
 | |
|   int rax = vid.axes;
 | |
|   if(rax == 1) rax = drawstaratvec(dx, dy) ? 2 : 0;
 | |
|   
 | |
|   if(rax == 0 || vid.axes >= 4) return;
 | |
| 
 | |
|   int starcol = getcs().uicolor;
 | |
|   ignore(starcol);
 | |
|   
 | |
|   if(0);
 | |
| 
 | |
| #if CAP_SHAPES
 | |
|   else if(vid.axes == 3)
 | |
|     queuepoly(Centered, cgi.shMovestar, starcol);
 | |
| #endif
 | |
|   
 | |
|   else for(int d=0; d<8; d++) {
 | |
| #if CAP_QUEUE
 | |
|     color_t col = starcol;
 | |
| #if ISPANDORA
 | |
|     if(leftclick && (d == 2 || d == 6 || d == 1 || d == 7)) col &= 0xFFFFFF3F;
 | |
|     if(rightclick && (d == 2 || d == 6 || d == 3 || d == 5)) col &= 0xFFFFFF3F;
 | |
|     if(!leftclick && !rightclick && (d&1)) col &= 0xFFFFFF3F;
 | |
| #endif
 | |
|     queueline(tC0(Centered), Centered * xspinpush0(d * 45._deg, cgi.scalefactor/2), col, 3 + vid.linequality);
 | |
| #endif
 | |
|     }
 | |
|   }
 | |
| 
 | |
| }
 | 
