1. // CSprite class
  2.  
  3. #include "csprite.h"
  4.  
  5.  
  6. int CCombatInfo::getOffense() // returns offensive value (attack)
  7. {
  8.     return offense;
  9. };
  10.  
  11. int CCombatInfo::getDefense() // returns defensive modifier (armor)
  12. {
  13.     return defense;
  14. };
  15.  
  16. void CCombatInfo::setHP(int newHP)
  17. {
  18.     health = newHP;
  19. };
  20.  
  21. int CCombatInfo::curHP()
  22. {
  23.     return health;
  24. };
  25.  
  26. void CCombatInfo::modHP(int mod)
  27. {
  28.     health += mod;
  29. }
  30.  
  31. void CCombatInfo::setOffense(int newOff)
  32. {
  33.     offense = newOff;  
  34. }
  35. void CCombatInfo::setDefense(int newDef)
  36. {
  37.     defense = newDef;  
  38. }
  39. void CCombatInfo::modOff(int mod)
  40. {
  41.     offense += mod;
  42. }
  43. void CCombatInfo::modDef(int mod)
  44. {
  45.     defense += mod;
  46. }
  47.  
  48. CCombatInfo::CCombatInfo(int Offense, int Defense, int Health) //, int AP) // constructor
  49. {
  50.     offense = Offense;
  51.     defense = Defense;
  52.     health  = Health;
  53. };
  54.  
  55. void CUnitStats::setMaxHP(int newMax)
  56. {
  57.     maxHealth = newMax;
  58. }
  59. int CUnitStats::fullHP()
  60. {
  61.     return maxHealth;  
  62. }
  63. int CUnitStats::fullMana()
  64. {
  65.     return maxMana;
  66. }
  67.  
  68. // returns the OFFENSE for unit
  69. int CUnitStats::getOff()
  70. {
  71.     return ((Str + Con + Lck)/3);  
  72. }
  73.  
  74. // returns the DEFENSE for unit
  75. int CUnitStats::getDef()
  76. {
  77.     return ((Dex + Int + Wis)/3);  
  78. };
  79.  
  80. int CUnitStats::getValue(int Stat)
  81. {
  82.     switch(Stat)
  83.     {
  84.     case STRENGTH:     return Str; break;
  85.     case DEXTERITY:    return Dex; break;
  86.     case CONSTITUTION: return Con; break;
  87.     case WISDOM:       return Wis; break;
  88.     case INTELLIGENCE: return Int; break;
  89.     case LUCK    :     return Lck; break;
  90.     default : return -1; // unknown
  91.     };
  92. };
  93.    
  94. void CUnitStats::setStat(int Stat, int Value)
  95. {
  96.     switch(Stat)
  97.     {
  98.     case STRENGTH:     Str=Value; break;
  99.     case DEXTERITY:    Dex=Value; break;
  100.     case CONSTITUTION: Con=Value; break;
  101.     case WISDOM:       Wis=Value; break;
  102.     case INTELLIGENCE: Int=Value; break;
  103.     case LUCK:         Lck=Value; break;
  104.     }; 
  105. };
  106.  
  107. void CUnitStats::modStat(int Stat, int Change) // to permanently increase or decrease a statistic
  108. {
  109.     switch(Stat)
  110.     {
  111.     case STRENGTH:     Str+=Change; break;
  112.     case DEXTERITY:    Dex+=Change; break;
  113.     case CONSTITUTION: Con+=Change; break;
  114.     case WISDOM:       Wis+=Change; break;
  115.     case INTELLIGENCE: Int+=Change; break;
  116.     case LUCK:         Lck+=Change; break;
  117.     }; 
  118. };
  119.  
  120. CUnitStats::CUnitStats() // default constructor
  121. {
  122.     do
  123.     {
  124.     Str =  5 + rand() % 15; // 3 - 20
  125.     Con =  6 + rand() % 15;
  126.     Dex =  7 + rand() % 15;
  127.     Wis =  8 + rand() % 15;
  128.     Lck =  9 + rand() % 15;
  129.     Int = 10 + rand() % 15;
  130.     }
  131.     while (Str+Dex+Con+Wis+Int+Lck <60);
  132.     // make sure they arent too low
  133.  
  134.     maxHealth = Str + Dex + Con; // phsyical stamina
  135.     maxMana   = Wis + Int + Lck; // magical power
  136. };
  137.  
  138.  
  139.     // will assign default value based on random numbers
  140. CUnitStats::CUnitStats(int s, int d, int c, int w, int i, int l) // constructor
  141. {
  142.     Str = s;
  143.     Dex = d;
  144.     Con = c;
  145.     Wis = w;
  146.     Int = i;
  147.     Lck = l;
  148.     maxHealth = Str + Dex + Con; // phsyical stamina
  149.     maxMana   = Wis + Int + Lck; // magical power
  150. };
  151.  
  152. void CSprite::Heal()
  153. {
  154.     Combat->setHP(Stats->fullHP());
  155. }
  156. int CSprite::curMana()      // returns current mana
  157. {
  158.     return mana;
  159. }
  160. bool CSprite::modMana(int modifier)
  161. {
  162.     if (mana + modifier < 0)
  163.         return false;
  164.     //else
  165.  
  166.     mana += modifier;
  167.  
  168.     if ( mana > Stats->fullMana() )
  169.         mana = Stats->fullMana();
  170.  
  171.     return true;
  172. }
  173.  
  174. void CSprite::setHP(int newHP)
  175. {
  176.     Combat->setHP(newHP);
  177.     Stats->setMaxHP(newHP);
  178. };
  179.  
  180. // returns 0 if still alive, 1 if dying/dead
  181. bool CSprite::doDamage(int damage)
  182. {
  183.     Combat->modHP(-damage);
  184.  
  185.     if (Combat->curHP() < 1)
  186.     {
  187.         Combat->setHP(0); // no negative numbers
  188.         STATE = DYING;
  189.         return true;
  190.     }
  191.     // else
  192.     return false;
  193. };
  194.  
  195. int CSprite::nextFrame()
  196. {
  197.     if (++animcount > animdelay)
  198.         animcount=0;
  199.     else
  200.         return 0; // use anim delay to slow down animations
  201.  
  202.     // increments current frame and checks for max
  203.     if (++curframe > lastframe)
  204.     {
  205.         curframe=1;
  206.         return 1;
  207.     }
  208.     else
  209.         return 0;
  210. }
  211. int CSprite::getFrame()
  212. {
  213.     return curframe;
  214. }
  215. void CSprite::setFrame(int newFrame)
  216. {
  217.     curframe=newFrame;
  218. }
  219. void CSprite::setLastFrame(int newLastFrame)
  220. {
  221.     lastframe = newLastFrame;
  222. }
  223. int CSprite::getLastFrame()
  224. {
  225.     return lastframe;
  226. }
  227.  
  228. void CSprite::setDelay(int newDelay)
  229. {
  230.     animdelay = newDelay;
  231. }
  232. int CSprite::getDelay()
  233. {
  234.     return animdelay;
  235. }
  236.  
  237. void CSprite::setupAnim(int numFrames, DIRS newDir, int perRow)
  238. {
  239.     curframe = 1;
  240.     lastframe = numFrames-1;
  241.     frames_per_anim = numFrames;
  242.     facingDir = newDir;
  243.     animdelay = 2;
  244.     animcount = 0;
  245.     columns = perRow; // sprite per row in sprite sheet
  246. }
  247.  
  248. void CSprite::setXY(int newX, int newY)
  249. {
  250.     x = newX;
  251.     y = newY;
  252. }  
  253.  
  254. void CSprite::setMoveXY(int moveX, int moveY)
  255. {
  256.     movex = moveX;
  257.     movey = moveY;
  258. }
  259.  
  260. int CSprite::getX()
  261. {
  262.     return x;
  263. }
  264. int CSprite::getY()
  265. {
  266.     return y;
  267. }
  268.  
  269. int CSprite::getMoveY()
  270. {
  271.     return movey;
  272. }
  273. void CSprite::setMoveY(int newY)
  274. {
  275.     movey = newY;
  276. }
  277.  
  278. int CSprite::getMoveX()
  279. {
  280.     return movex;
  281. }
  282. void CSprite::setMoveX(int newX)
  283. {
  284.     movex = newX;  
  285. }
  286.  
  287. void CSprite::setX(int newX)
  288. {
  289.     x = newX;  
  290. }
  291. void CSprite::addX(int addtoX)
  292. {
  293.     x += addtoX;
  294. }
  295.  
  296. void CSprite::setY(int newY)
  297. {
  298.     y = newY;  
  299. }
  300. void CSprite::addY(int addtoY)
  301. {
  302.     y += addtoY;
  303. }
  304.  
  305. int CSprite::getHeight()
  306. {
  307.     return height;
  308. }
  309. int CSprite::getWidth()
  310. {
  311.     return width;  
  312. }
  313.  
  314. void CSprite::doMove(bool SAFE = true)
  315. {
  316.  //move the sprite
  317.     x += movex;
  318.     y += movey;
  319.  
  320.     if (SAFE)
  321.     {
  322.         // stop at edge, dont wrap
  323.         if (x > border.right) // RIGHT
  324.         {
  325.             x=border.right;
  326.             movex=0;
  327.             movey=0;
  328.             moving=false;
  329.         }
  330.         else if (x < border.left) // LEFT
  331.         {
  332.             x=border.left;
  333.             movex=0;
  334.             movey=0;
  335.             moving=false;
  336.         }
  337.  
  338.        if (y > border.bottom) // BOTTOM
  339.        {
  340.             y= border.bottom;
  341.             movex=0;
  342.             movey=0;
  343.             moving=false;
  344.        }
  345.        else if (y < border.top) // TOP
  346.         {
  347.             y=border.top;
  348.             movex=0;
  349.             movey=0;
  350.             moving=false;
  351.         }
  352.     }
  353. }
  354.  
  355. LPDIRECT3DTEXTURE9 CSprite::getImage()
  356. {
  357.     return _image;
  358. }
  359.  
  360. // returns a rect pointing to the sprites frame
  361. RECT CSprite::getRect()
  362. {
  363.     /*  EAST    = 1,
  364.         NORTH   = 2,
  365.         NE      = 3,
  366.         NW      = 4,
  367.         SOUTH   = 5,
  368.         SE      = 6,
  369.         SW      = 7,
  370.         WEST    = 8     */
  371.     int offset; // offset starting location based on direction sprite is facing
  372.     offset = (facingDir-1) * frames_per_anim; //
  373.  
  374.     RECT srcRect;
  375.  
  376.     // will return the RECT point to current sprite, within sprite sheet       
  377.     srcRect.left   = ((curframe+offset) % columns) * width;
  378.     srcRect.top    = ((curframe+offset) / columns) * height;
  379.     srcRect.right  = srcRect.left + width;
  380.     srcRect.bottom = srcRect.top  + height;
  381.    
  382.     return srcRect;
  383. }
  384.  
  385. DIRS CSprite::getFacing()
  386. {
  387.     return facingDir;
  388. }
  389.  
  390. void CSprite::setFacing(DIRS newFacing, bool changeMoveXY)
  391. {
  392.     facingDir = newFacing;
  393.  
  394.     if (changeMoveXY)
  395.         switch(newFacing)
  396.         {
  397.             case  NORTH:    movey=-2;               break;  // NORTH
  398.             case  SOUTH:    movey= 2;               break;  // SOUTH
  399.             case  EAST:     movex= 2;               break;  // EAST
  400.             case  WEST:     movex=-2;               break;  // WEST
  401.             case  NE:       movex= 2;   movey=-1;   break;  // NE
  402.             case  NW:       movex=-2;   movey=-1;   break;  // NW
  403.             case  SE:       movex= 2;   movey= 1;   break;  // SE
  404.             case  SW:       movex=-2;   movey= 1;   break;  // SW
  405.         };
  406. }
  407.  
  408. // check movement keys
  409. void CSprite::checkArrowsKeys()
  410. {
  411.    if (KEY_DOWN(VK_UP) || KEY_DOWN(VK_NUMPAD8))
  412.     {// move NORTH     
  413.         movey=-2;
  414.         movex=0;
  415.         facingDir=NORTH;
  416.         moving=true;               
  417.     }
  418.     else if (KEY_DOWN(VK_RIGHT) || KEY_DOWN(VK_NUMPAD6))   
  419.     {
  420.         moving=true;
  421.         movex=2;
  422.         movey=0;
  423.         facingDir=EAST;
  424.  
  425.     }
  426.     else if (KEY_DOWN(VK_DOWN) || KEY_DOWN(VK_NUMPAD2))
  427.     {
  428.         movey=2;
  429.         movex=0;
  430.         facingDir=SOUTH;
  431.         moving=true;
  432.     }
  433.     else if (KEY_DOWN(VK_LEFT) || KEY_DOWN(VK_NUMPAD4))
  434.     {
  435.         movey=0;
  436.         movex=-2;
  437.         facingDir=WEST;
  438.         moving=true;
  439.     }
  440.     else if (KEY_DOWN(VK_NUMPAD5))
  441.     {
  442.         // stop
  443.         movex=0;
  444.         movey=0;
  445.         moving=false;
  446.     }
  447.     else if (KEY_DOWN(VK_NUMPAD9)) // NE
  448.     {
  449.         movex=2;
  450.         movey=-1;
  451.         facingDir=NE;
  452.         moving=true;
  453.     }
  454.     else if (KEY_DOWN(VK_NUMPAD7)) // NW
  455.     {
  456.         movex=-2;
  457.         movey=-1;
  458.         facingDir=NW;
  459.         moving=true;
  460.     }
  461.     else if (KEY_DOWN(VK_NUMPAD3)) // SE
  462.     {
  463.         movex=2;
  464.         movey=1;
  465.         facingDir=SE;
  466.         moving=true;
  467.     }
  468.     else if (KEY_DOWN(VK_NUMPAD1)) // SW
  469.     {
  470.         movex=-2;
  471.         movey=1;
  472.         facingDir=SW;
  473.         moving=true;
  474.     };
  475.     lastDir = facingDir;
  476. } // end arrow key checks
  477.  
  478. bool CSprite::isMoving()
  479. {
  480.     return moving;
  481. }
  482.  
  483. void CSprite::setMoving(bool newState)
  484. {
  485.     moving = newState; 
  486. }
  487.  
  488. void CSprite::setRhombus()
  489. {
  490.     // RHOMBUSHEIGHT
  491.     // this will return the "iso diamond" at the bottom of the sprite
  492.     int divisor = 2;
  493.  
  494.     // X
  495.     int center = x + (width /2);
  496.     rhombus.left  = center - (RHOMBUSWIDTH/divisor);
  497.     rhombus.right = center + (RHOMBUSWIDTH/divisor)+1;
  498.  
  499.     center = (y + height) - (RHOMBUSHEIGHT*1.25);
  500.     rhombus.top    = center - (RHOMBUSHEIGHT/divisor);
  501.     rhombus.bottom = center + (RHOMBUSHEIGHT/divisor)+1;
  502. }
  503.  
  504. RECT CSprite::getRhombus()
  505. {
  506.     // RHOMBUSHEIGHT
  507.     // this will return the "iso diamond" at the bottom of the sprite
  508.     // 32x32 RECT now - works easiery and quicker
  509.     int divisor = 2;
  510.  
  511.     // X
  512.     int center = x + (width /2);
  513.     rhombus.left  = center - (RHOMBUSWIDTH/divisor);
  514.     rhombus.right = center + (RHOMBUSWIDTH/divisor)+1;
  515.  
  516.     center = (y + height) - (RHOMBUSHEIGHT);//
  517.     rhombus.top    = center - (RHOMBUSHEIGHT/divisor);
  518.     rhombus.bottom = center + (RHOMBUSHEIGHT/divisor)+1;
  519.  
  520.     return rhombus;
  521. }
  522.  
  523. POINT CSprite::getScreenPT()
  524. {
  525.     POINT tPT;
  526.     tPT.x = x;
  527.     tPT.y = y;
  528.  
  529.     return tPT;
  530. }
  531.  
  532. void CSprite::setNewDIR(int newDir)
  533. {
  534.     switch(newDir)
  535.     {
  536.         case  1: movey=-2;              facingDir = NORTH;  break;  // NORTH
  537.         case  2: movey= 2;              facingDir = SOUTH;  break;  // SOUTH
  538.         case  3: movex= 2;              facingDir = EAST;   break;  // EAST
  539.         case  4: movex=-2;              facingDir = WEST;   break;  // WEST
  540.         case  5: movex= 2;  movey=-1;   facingDir = NE;     break;  // NE
  541.         case  6: movex=-2;  movey=-1;   facingDir = NW;     break;  // NW
  542.         case  7: movex= 2;  movey= 1;   facingDir = SE;     break;  // SE
  543.         case  8: movex=-2;  movey= 1;   facingDir = SW;     break;  // SW
  544.     };
  545. }
  546.  
  547. // defines the screen walkable/collision border for this sprite
  548. void CSprite::setBorder(int left, int right, int top, int bottom)
  549. {
  550.     border.left     = left;
  551.     border.right    = right;
  552.     border.top      = top;
  553.     border.bottom   = bottom;
  554. }
  555.  
  556. // returns TRUE if sprite is within its defined border, FALSE otherwise
  557. bool CSprite::hitBorder()
  558. {
  559.         // see if it is inside the border boundaries
  560.     return ( (x > border.right) || (x < border.left) || (y > border.bottom) || (y < border.top) );
  561. }
  562.  
  563. void CSprite::setSTATE(STATEtype newS)
  564. {
  565.     STATE = newS;
  566. }
  567.  
  568. int CSprite::getSTATE()
  569. {
  570. //  INACTIVE    = 0,
  571. //  ACTIVE      = 1,        // moving
  572. //  CASTING     = 2,
  573. //  ATTACKING   = 3,
  574. //  DYING       = 6
  575. //  STATEtype STATE;
  576.     return STATE;
  577. }
  578.  
  579. POINT CSprite::getAnchor()
  580. {
  581.     POINT tPT;
  582.  
  583.     // for a 96x96 sprite, this is {45,64}
  584.     tPT.x = x + width/2;
  585.     tPT.y = y + height - 32;
  586.  
  587.     return tPT;
  588. }
  589.  
  590. // constructor for new sprites ... curFrame will always be (1) .. scale and rotation not currently implemented
  591. // and this is for non-animated sprites
  592. CSprite::CSprite(int X, int Y, int Width, int Height, char *Filename)
  593. {
  594.     x = X;
  595.     y = Y;
  596.     width = Width;
  597.     height = Height;
  598.  
  599.     // initialize these, but not currently in use since this is non-animated sprite
  600.     curframe = lastframe = 1;
  601.     animdelay = 3;
  602.     animcount = 0;
  603.     movex = movey = 0;
  604.     facingDir = EAST; // default
  605.     setRhombus();
  606.  
  607.     // Units stats
  608.     Stats   = new CUnitStats();
  609.    
  610.     // assign full HP and generate offense/defense
  611.     Combat  = new CCombatInfo(Stats->getOff(),Stats->getDef(),Stats->fullHP());
  612.    
  613.     // Sets STATS (Str,Dex,Con,Wis,Int,Lck) and SKILLS Offense/Defense/Mana/Health
  614.  
  615.     // set intial
  616.     mana = Stats->fullMana();
  617.    
  618.     // Load the sprite file
  619.     LoadImage(Filename);       
  620. }
  621.  
  622. // destructor -- the default one should release all memory allocated for this sprite
  623.  CSprite::~CSprite(void)
  624. {
  625.     // release the sprite sheet
  626.     _image->Release(); 
  627.    
  628. }
  629.  
  630.  
  631. void CSprite::LoadImage(char *Filename)
  632. {
  633.     _image = LoadTexture(Filename, D3DCOLOR_XRGB(255,0,255));
  634.     assert(_image);        
  635. }