⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 creature.cpp

📁 S.C.O.U.R.G.E.是一款类似Rogue的游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************                          creature.cpp  -  description                             -------------------    begin                : Sat May 3 2003    copyright            : (C) 2003 by Gabor Torok    email                : cctorok@yahoo.com ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/#include "creature.h"/** * Formations are defined by 4 set of coordinates in 2d space. * These starting positions assume dir=Constants::MOVE_UP */static const Sint16 layout[][4][2] = {  { {0, 0}, {-1, 1}, {1, 1}, {0, 2}},  // DIAMOND_FORMATION  { {0, 0}, {-1, 1}, {0, 1}, {-1, 2}},  // STAGGERED_FORMATION  { {0, 0}, {1, 0}, {1, 1}, {0, 1}},   // SQUARE_FORMATION  { {0, 0}, {0, 1}, {0, 2}, {0, 3}},   // ROW_FORMATION  { {0, 0}, {-2, 2}, {0, 2}, {2, 2}},  // SCOUT_FORMATION  { {0, 0}, {-1, 1}, {1, 1}, {0, 3}}   // CROSS_FORMATION};Creature::Creature(Scourge *scourge, Character *character, char *name) {  this->scourge = scourge;  this->character = character;  this->monster = NULL;  this->name = name;  this->model_name = character->getModelName();  this->skin_name = character->getSkinName();  sprintf(description, "%s the %s", name, character->getName());  this->speed = 50;  this->motion = Constants::MOTION_MOVE_TOWARDS;    this->armor=0;  this->bonusArmor=0;  this->thirst=10;  this->hunger=10;    this->shape = scourge->getShapePalette()->getCreatureShape(model_name, skin_name);  commonInit();  }Creature::Creature(Scourge *scourge, Monster *monster) {  this->scourge = scourge;  this->character = NULL;  this->monster = monster;  this->name = monster->getType();  this->model_name = monster->getModelName();  this->skin_name = monster->getSkinName();  sprintf(description, "You see %s", monster->getType());  this->speed = monster->getSpeed();  this->motion = Constants::MOTION_LOITER;  this->armor = monster->getBaseArmor();  this->bonusArmor=0;  this->shape = scourge->getShapePalette()->getCreatureShape(model_name,                                                              skin_name,                                                              monster->getScale(),                                                             monster->getWidth(),                                                             monster->getDepth(),                                                             monster->getHeight());  commonInit();  monsterInit();}void Creature::commonInit() {  this->x = this->y = this->z = 0;  this->dir = Constants::MOVE_UP;  this->next = NULL;  this->formation = DIAMOND_FORMATION;  this->index = 0;  this->tx = this->ty = -1;    this->selX = this->selY = -1;  this->quadric = gluNewQuadric();  this->inventory_count = 0;  for(int i = 0; i < Character::INVENTORY_COUNT; i++) {    equipped[i] = MAX_INVENTORY_SIZE;  }  for(int i = 0; i < Constants::SKILL_COUNT; i++) {    skillMod[i] = skillBonus[i] = 0;  }  this->stateMod = 0;  this->level = 1;  this->exp = 0;  this->hp = 0;  this->mp = 0;  this->startingHp = 0;  this->startingMp = 0;  this->ac = 0;  this->targetCreature = NULL;  this->targetX = this->targetY = this->targetZ = 0;  this->targetItem = NULL;  this->lastTick = 0;  this->moveRetrycount = 0;  this->cornerX = this->cornerY = -1;  this->lastTurn = 0;  this->damageEffectCounter = 0;  this->effectDuration = Constants::DAMAGE_DURATION;  this->effect = new Effect(scourge, scourge->getShapePalette(), shape);  this->effectType = Constants::EFFECT_FLAMES;  this->facingDirection = Constants::MOVE_UP; // good init ?  this->availableSkillPoints = 0;  this->minRange = this->maxRange = 0;  this->failedToMoveWithinRangeAttemptCount = 0;  this->action = Constants::ACTION_NO_ACTION;  this->actionItem = NULL;  this->actionSpell = NULL;  this->preActionTargetCreature = NULL;  // Yes, monsters have inventory weight issues too  inventoryWeight =  0.0f;    for(int i = 0; i < inventory_count; i++) {    inventoryWeight += inventory[i]->getRpgItem()->getWeight();  }    this->money = this->level * (int)(10.0f * rand()/RAND_MAX);  calculateExpOfNextLevel();}void Creature::calculateExpOfNextLevel() {  if(isMonster()) return;  expOfNextLevel = 0;  for(int i = 0; i < level; i++) {    expOfNextLevel += ((i + 1) * character->getLevelProgression());  }}Creature::~Creature(){  delete effect;  // do this before deleting the shape  scourge->getShapePalette()->decrementSkinRefCount(skin_name);  delete shape;}// moving monsters onlybool Creature::move(Uint16 dir, Map *map) {  if(character) return false;  // a hack for runaway creatures  if(!(x > 10 && x < MAP_WIDTH - 10 &&       y > 10 && y < MAP_DEPTH - 10)) {    if(monster) cerr << "hack for " << getName() << endl;    return false;  }  int nx = x;  int ny = y;  int nz = z;  switch(dir) {  case Constants::MOVE_UP:        ny = y - 1;    break;  case Constants::MOVE_DOWN:        ny = y + 1;    break;  case Constants::MOVE_LEFT:    nx = x - 1;    break;  case Constants::MOVE_RIGHT:        nx = x + 1;    break;  }  setFacingDirection(dir);  map->removeCreature(x, y, z);  Location *loc = map->getBlockingLocation(getShape(), nx, ny, nz);  Item *item = NULL;  if(loc) item = loc->item;  if(!loc || (item && !item->isBlocking())) {    // pick up item    if(item) {      addInventory(item);      char message[100];      sprintf(message, "%s picks up %s.",               getName(),               item->getItemName());      scourge->getMap()->addDescription(message);    }    map->setCreature(nx, ny, nz, this);    ((MD2Shape*)shape)->setDir(dir);    moveTo(nx, ny, nz);    setDir(dir);            return true;  } else {    // move back    map->setCreature(x, y, z, this);        return false;  }}bool Creature::follow(Map *map) {  // find out where the creature should be relative to the formation  Sint16 px, py, pz;  getFormationPosition(&px, &py, &pz);  setSelXY(px, py);  return true; }void Creature::setSelXY(int x, int y, bool force) {   selX = x;   selY = y;   moveRetrycount = 0;   setMotion(Constants::MOTION_MOVE_TOWARDS);     if(force) {    tx = ty = -1;  }  // if we're trying to move within a range, try a number of times  adjustMovementToRange();}/**   Return true only if a range is specified and we're within it. */bool Creature::isInRange() {  if(maxRange > 0) {    float d = getDistanceToTarget();    //cerr << "\tisInRange: dist=" << d << " min=" << minRange << " max=" << maxRange << endl;    return(d >= minRange && d < maxRange);  }  return false;}/**   Check that we're within range (if range specified).   If not, try n times, then wait n times before trying again.*/void Creature::adjustMovementToRange() {  if(maxRange <= 0 || !hasTarget()) return;  float d = getDistanceToTarget();  bool inRange = (d >= minRange && d < maxRange);  if(inRange) {    // we're in range: stop moving    failedToMoveWithinRangeAttemptCount = 0;    stopMoving();    return;  } else if(failedToMoveWithinRangeAttemptCount < MAX_FAILED_MOVE_ATTEMPTS) {    // we're not in range: move away if too close    failedToMoveWithinRangeAttemptCount++;    // if too close, move away    if(d < minRange) {      Sint16 nz;      findCorner(&cornerX, &cornerY, &nz);      setMotion(Constants::MOTION_MOVE_AWAY);    }    return;  } else if(failedToMoveWithinRangeAttemptCount < MAX_FAILED_MOVE_ATTEMPTS * 2) {    // we're still not in range: return true to continue attacks and not try to position forever    failedToMoveWithinRangeAttemptCount++;    return;  } else {    // we're still not in range but continue to try to position creature    failedToMoveWithinRangeAttemptCount = 0;    return;  }}void Creature::setTargetCreature(Creature *c) {   targetCreature = c;   if(!c) {    setDistanceRange(0, 0);  }}void Creature::stopMoving() {  bestPathPos = (int)bestPath.size();  selX = selY = -1;}bool Creature::moveToLocator(Map *map) {  // Don't move when attacking...  // this is actually wrong, the method should not be called in this  // case, but the code is simpler this way. (Returning false is   // is incorrect.)  if(((MD2Shape*)getShape())->getAttackEffect()) return false;  // don't move when in range  if(isInRange()) return false;  bool moved = false;  if(selX > -1) {    // take a step    if(getMotion() == Constants::MOTION_MOVE_AWAY){          //if(this == scourge->getParty()->getParty(1)) cerr << "Barlett: moving away! attempt=" << failedToMoveWithinRangeAttemptCount << endl;      moved = gotoPosition(map, cornerX, cornerY, 0, "cornerXY");    } else {      //if(this == scourge->getParty()->getParty(1)) cerr << "Barlett: moving towards! attempt=" << failedToMoveWithinRangeAttemptCount << " min=" << minRange << " max=" << maxRange << endl;      moved = gotoPosition(map, selX, selY, 0, "selXY");    }    // if we've no more steps    if((int)bestPath.size() <=  bestPathPos && selX > -1) {          // if we're not there yet, and it's possible to stand there, recalc steps      if(!(selX == getX() && selY == getY()) &&         map->shapeFits(getShape(), selX, selY, -1) &&         moveRetrycount < MAX_MOVE_RETRY) {        // don't keep trying forever        moveRetrycount++;        tx = ty = -1;      } else {        // do this so the animation switches to "stand"        stopMoving();      }         // if this is the player, return to regular movement      if(this == scourge->getParty()->getPlayer()) {        scourge->getParty()->setPartyMotion(Constants::MOTION_MOVE_TOWARDS);      }    }  }  return moved;}bool Creature::anyMovesLeft() {  return(selX > -1 && (int)bestPath.size() > bestPathPos); }bool Creature::gotoPosition(Map *map, Sint16 px, Sint16 py, Sint16 pz, char *debug) {  // If the target moved, get the best path to the location  if(!(tx == px && ty == py)) {    //    cerr << getName() << " - " << debug << " steps left: " <<     //      ((int)bestPath.size() - bestPathPos) << " out of " << (int)bestPath.size() << endl;    tx = px;    ty = py;    bestPathPos = 1; // skip 0th position; it's the starting location    Util::findPath(getX(), getY(), getZ(), px, py, pz, &bestPath, scourge->getMap(), getShape());  }  if((int)bestPath.size() > bestPathPos) {    // take a step on the bestPath    Location location = bestPath[bestPathPos];    // if we can't step there, someone else has moved there ahead of us    Uint16 oldDir = dir;    //dir = next->getDir();    if(getX() < location.x) dir = Constants::MOVE_RIGHT;    else if(getX() > location.x) dir = Constants::MOVE_LEFT;    else if(getY() < location.y) dir = Constants::MOVE_DOWN;    else if(getY() > location.y) dir = Constants::MOVE_UP;    setFacingDirection(dir);    Location *position = map->moveCreature(getX(), getY(), getZ(),                                           location.x, location.y, getZ(),                                           this);    if(!position) {      bestPathPos++;      moveTo(location.x, location.y, getZ());      ((MD2Shape*)shape)->setDir(dir);      return true;    } else {          dir = oldDir;      /*      commented out: this doesn't really work... the player will block forever      if 'creature' can't move          // if another party member is blocking the player,       // make them move out of the way      Creature *creature = position->creature;        if(this == scourge->getParty()->getPlayer() &&        creature && creature->character && scourge->getParty()->getPlayer() != creature) {            creature->moveRetrycount++;      if(creature->moveRetrycount < MAX_MOVE_RETRY) {        Sint16 nz;        creature->findCorner(&creature->cornerX, &creature->cornerY, &nz);        //	    creature->gotoPosition(map, nx, ny, nz, "corner");        creature->setMotion(Constants::MOTION_MOVE_AWAY);      } else {        // do this so the animation switches to "stand"        creature->stopMoving();      }      } else {	        */      // if we're not at the destination, but it's possible to stand there

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -