123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OBULLETA.CPP
- //Description : Object Bullet Array
- //Owner : Alex
- #include <OVGA.h>
- #include <OUNIT.h>
- #include <OBULLET.h>
- #include <OWORLD.h>
- #include <OTOWN.h>
- #include <OB_PROJ.h>
- #include <OB_HOMIN.h>
- #include <OB_FLAME.h>
- //--------- Begin of function BulletArray::BulletArray ---------//
- //
- // <int> initArraySize - the initial size of this array.
- //
- BulletArray::BulletArray(int initArraySize) : SpriteArray(initArraySize)
- {
- }
- //----------- End of function BulletArray::BulletArray -----------//
- //--------- Begin of function BulletArray::create_bullet ---------//
- //
- // return: <int> the recno of the bullet created.
- //
- int BulletArray::create_bullet(short spriteId, Bullet** bpp)
- {
- Bullet* bulletPtr;
- SpriteInfo *spriteInfo = sprite_res[spriteId];
- err_when(!spriteInfo);
- err_when(spriteInfo->sprite_type != 'B');
- switch(spriteInfo->sprite_sub_type)
- {
- case 0:
- case ' ':
- bulletPtr = new Bullet;
- break;
- case 'P':
- bulletPtr = new Projectile;
- break;
- case 'H':
- bulletPtr = new BulletHoming;
- break;
- case 'F':
- bulletPtr = new BulletFlame;
- break;
- default:
- err_here(); // undefined bullet type
- if( bpp )
- *bpp = NULL;
- return 0;
- }
- add(bulletPtr);
- if( bpp )
- *bpp = bulletPtr;
- return recno();
- }
- //----------- End of function BulletArray::create_bullet -----------//
- //--------- Begin of function BulletArray::bullet_class_size ---------//
- int BulletArray::bullet_class_size(int spriteId)
- {
- SpriteInfo *spriteInfo = sprite_res[spriteId];
- err_when(spriteInfo->sprite_type != 'B');
- switch(spriteInfo->sprite_sub_type)
- {
- case 0:
- case ' ':
- return sizeof(Bullet);
- case 'P':
- return sizeof(Projectile);
- case 'H':
- return sizeof(BulletHoming);
- case 'F':
- return sizeof(BulletFlame);
- default:
- err_here(); // undefined bullet type
- return 0;
- }
- }
- //----------- End of function BulletArray::bullet_class_size -----------//
- //--------- Begin of function BulletArray::bullet_path_possible ---------//
- // For default bullet:
- // if the bullet is not blocked by building in its path, this
- // function return 1 for success, otherwise return 0.
- // For projectile bullet:
- // always return 1
- //
- int BulletArray::bullet_path_possible(short startXLoc, short startYLoc, char attackerMobileType,
- short destXLoc, short destYLoc, char targetMobileType,
- char bulletSpeed, short bulletSpriteId)
- {
- if(attackerMobileType==UNIT_AIR || targetMobileType==UNIT_AIR)
- return 1;
- //-------- skip the checking for projectile -----------//
- SpriteInfo *spriteInfo = sprite_res[bulletSpriteId];
- if(spriteInfo->sprite_sub_type == 'P')
- return 1;
- err_when(spriteInfo->sprite_sub_type == 'P');
- //----------------------- define variables ---------------//
- int originX = startXLoc*ZOOM_LOC_WIDTH;
- int originY = startYLoc*ZOOM_LOC_HEIGHT;
- int goX = destXLoc*ZOOM_LOC_WIDTH;
- int goY = destYLoc*ZOOM_LOC_HEIGHT;
- int xStep = (goX - originX)/bulletSpeed;
- int yStep = (goY - originY)/bulletSpeed;
- int totalStep = max(1, max(abs(xStep), abs(yStep)));
- int curStep = 0;
- //------------------------------------------------------//
- // if the path of the bullet is blocked, return 0
- //------------------------------------------------------//
- int curX = originX + ZOOM_LOC_WIDTH/2;
- int curY = originY + ZOOM_LOC_HEIGHT/2;
- int curXLoc, curYLoc;
- Location *locPtr;
- while(curStep++<totalStep)
- {
- err_when(curStep > 200);
- curX += xStep;
- curY += yStep;
- curXLoc = curX/ZOOM_LOC_WIDTH;
- curYLoc = curY/ZOOM_LOC_HEIGHT;
- if(curXLoc==startXLoc && curYLoc==startYLoc)
- continue;
- if(curXLoc==destXLoc && curYLoc==destYLoc)
- break; // is destination
- locPtr = world.get_loc(curXLoc, curYLoc);
- //### begin alex 2/6 ###//
- //if(!locPtr->walkable(3) || locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA))
- if(!locPtr->walkable(3))
- //#### end alex 2/6 ####//
- return 0;
- }
- return 1;
- }
- //----------- End of function BulletArray::bullet_path_possible -----------//
- //--------- Begin of function BulletArray::add_bullet_possible ---------//
- // call bullet_possible to check whether bullets emitted from this position
- // can reach the target location with blocking
- //
- // return 1 if bullets are able to reach the target location
- // return 0 if not
- //
- int BulletArray::add_bullet_possible(short startXLoc, short startYLoc, char attackerMobileType,
- short targetXLoc, short targetYLoc, char targetMobileType,
- short targetWidth, short targetHeight, short& resultXLoc, short& resultYLoc,
- char bulletSpeed, short bulletSpriteId)
- {
- resultXLoc = resultYLoc = -1;
- //----------------------------------------------------------------------//
- // for target with size 1x1
- //----------------------------------------------------------------------//
- if(targetWidth==1 && targetHeight==1)
- {
- if(bullet_path_possible(startXLoc, startYLoc, attackerMobileType, targetXLoc, targetYLoc, targetMobileType, bulletSpeed, bulletSpriteId))
- {
- resultXLoc = targetXLoc;
- resultYLoc = targetYLoc;
- return 1;
- }
- else
- return 0;
- }
- err_when(targetWidth==1 && targetHeight==1);
- //----------------------------------------------------------------------//
- // choose the closest corner to be the default attacking point of range attack
- //
- // generalized case for range-attack is coded below. Work for target with
- // size > 1x1
- //----------------------------------------------------------------------//
- //-------------- define parameters --------------------//
- short adjWidth = targetWidth-1; // adjusted width;
- short adjHeight = targetHeight-1; // adjusted height
- short xOffset=0, yOffset=0; // the 1st(default) location for range attack
- short atEdge = 0; // i.e. the attacking point is at the corner or edge of the target
- // 1 for at the edge, 0 for at corner
-
- //----------------------------------------------------------------------//
- // determine initial xOffset
- //----------------------------------------------------------------------//
- if(startXLoc <= targetXLoc)
- xOffset = 0; // the left hand side of the target
- else if(startXLoc >= targetXLoc+adjWidth)
- xOffset = adjWidth; // the right hand side of the target
- else
- {
- xOffset = startXLoc - targetXLoc; // in the middle(vertical) of the target
- atEdge++;
- }
- //----------------------------------------------------------------------//
- // determine initial yOffset
- //----------------------------------------------------------------------//
- if(startYLoc <= targetYLoc)
- yOffset = 0; // the upper of the target
- else if(startYLoc >= targetYLoc+adjHeight)
- yOffset = adjHeight;
- else
- {
- yOffset = startYLoc - targetYLoc; // in the middle(horizontal) of the target
- atEdge++;
- }
- //----------------------------------------------------------------------//
- // checking whether it is possible to add bullet
- //----------------------------------------------------------------------//
- if(bullet_path_possible(startXLoc, startYLoc, attackerMobileType, targetXLoc+xOffset, targetYLoc+yOffset, targetMobileType, bulletSpeed, bulletSpriteId))
- {
- resultXLoc = targetXLoc+xOffset;
- resultYLoc = targetYLoc+yOffset;
- return 1;
- }
- short leftXOffset, leftYOffset;
- short rightXOffset, rightYOffset;
- short leftX, leftY, rightX, rightY;
- short found=0; // found a location to attack the target and the path is not blocked
- short end=0;
-
- if(atEdge) // only check one edge of the target
- {
- if(xOffset==0 || xOffset==adjWidth) // horizontal edge
- {
- leftYOffset = rightYOffset = 0;
- leftXOffset = 1;
- rightXOffset = -1;
- }
- else if(yOffset==0 || yOffset==adjHeight) // vertical edge
- {
- leftXOffset = rightXOffset = 0;
- leftYOffset = 1;
- rightYOffset = -1;
- }
- else
- err_here(); // the sprite is within the target ???
- }
- else // at the corner, need to check two edges of the target
- {
- leftYOffset = rightXOffset = 0;
- leftXOffset = (xOffset==0) ? 1 : -1;
- rightYOffset = (yOffset==0) ? 1 : -1;
- }
- leftX = rightX = xOffset;
- leftY = rightY = yOffset;
- while(!found)
- {
- end = 0;
-
- //-------------------------------------------//
- // for the leftX, leftY
- //-------------------------------------------//
- leftX += leftXOffset;
- leftY += leftYOffset;
- if(leftX>=0 && leftX<targetWidth && leftY>=0 && leftY<targetHeight)
- {
- if(bullet_path_possible(startXLoc, startYLoc, attackerMobileType, targetXLoc+leftX, targetYLoc+leftY, targetMobileType, bulletSpeed, bulletSpriteId))
- {
- resultXLoc = targetXLoc+leftX;
- resultYLoc = targetYLoc+leftY;
- return 1;
- }
- }
- else
- end++;
- //-------------------------------------------//
- // for the rightX, rightY
- //-------------------------------------------//
- rightX += rightXOffset;
- rightY += rightYOffset;
- if(rightX>=0 && rightX<targetWidth && rightY>=0 && rightY<targetHeight)
- {
- if(bullet_path_possible(startXLoc, startYLoc, attackerMobileType, targetXLoc+rightX, targetYLoc+rightY, targetMobileType, bulletSpeed, bulletSpriteId))
- {
- resultXLoc = targetXLoc+rightX;
- resultYLoc = targetYLoc+rightY;
- return 1;
- }
- }
- else
- {
- if(end) // all locations have been checked, all are blocked
- return 0;
- }
- }
- return 0;
- }
- //----------- End of function BulletArray::add_bullet_possible -----------//
- //--------- Begin of function BulletArray::add_bullet ---------//
- // unit attacks unit by bullet
- //
- // <Unit*> parentUnit - pointer to the attacking target unit
- // <Unit*> targetUnit - pointer to the target unit
- //
- // return 1 if bullet is added successfully otherwise return 0.
- //
- short BulletArray::add_bullet(Unit* parentUnit, Unit* targetUnit)
- {
- //------------------------------------------------------//
- // define parameters
- //------------------------------------------------------//
- SpriteInfo *targetSpriteInfo = targetUnit->sprite_info;
- AttackInfo *attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
- short attackXLoc = parentUnit->range_attack_x_loc;
- short attackYLoc = parentUnit->range_attack_y_loc;
- short targetXLoc = targetUnit->next_x_loc();
- short targetYLoc = targetUnit->next_y_loc();
- if(attackXLoc >= targetXLoc && attackXLoc < targetXLoc+targetSpriteInfo->loc_width &&
- attackYLoc >= targetYLoc && attackYLoc < targetYLoc+targetSpriteInfo->loc_height)
- {
- //-------------------------------------------------------//
- // the previous used range attack destination can be reused,
- // time is saved 'cos no need to check for bullet_path_possible()
- //-------------------------------------------------------//
- short bulletId = (parentUnit->attack_info_array+parentUnit->cur_attack)->bullet_sprite_id;
- Bullet* bulletPtr;
- create_bullet( bulletId, &bulletPtr);
- bulletPtr->init(BULLET_BY_UNIT, parentUnit->sprite_recno, attackXLoc, attackYLoc, targetUnit->mobile_type);
- err_when(parentUnit->cur_dir!=parentUnit->final_dir);
- //parentUnit->get_dir(parentUnit->next_x_loc(), parentUnit->next_y_loc(), attackXLoc, attackYLoc);
- return 1;
- }
- err_here();
- return 0;
- }
- //----------- End of function BulletArray::add_bullet -----------//
- //--------- Begin of function Bullet::add_bullet ---------//
- // Overload of add_bullet(), unit attack firm/town/wall
- //
- // <Unit*> parentUnit - pointer to the attacking target unit
- // <short> xLoc - the target upper left corner x loc
- // note: taregt can be firm, town or wall
- // <short> yLoc - the target upper left corner y loc
- //
- // return 1 if bullet is added successfully otherwise return 0.
- //
- // note: unit attacks firm or town by bullet will call this
- // function. The location of the firm or town is
- // specified by xLoc and yLoc.
- //
- short BulletArray::add_bullet(Unit* parentUnit, short xLoc, short yLoc)
- {
- //------------------------------------------------------//
- // define parameters
- //------------------------------------------------------//
- AttackInfo *attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
- short attackXLoc = parentUnit->range_attack_x_loc;
- short attackYLoc = parentUnit->range_attack_y_loc;
- short targetXLoc = xLoc;
- short targetYLoc = yLoc;
- short width, height;
- Firm* targetFirm = NULL;
- Town* targetTown = NULL;
- FirmInfo* firmInfo = NULL;
- Location* locPtr = world.get_loc(xLoc, yLoc);
-
- if(locPtr->is_firm())
- {
- targetFirm = firm_array[locPtr->firm_recno()];
- firmInfo = firm_res[targetFirm->firm_id];
- width = firmInfo->loc_width;
- height = firmInfo->loc_height;
- }
- else if(locPtr->is_town())
- {
- targetTown = town_array[locPtr->town_recno()];
- width = targetTown->loc_width();
- height = targetTown->loc_height();
- }
- else if(locPtr->is_wall())
- width = height = 1;
- else
- err_here();
- if(attackXLoc >= targetXLoc && attackXLoc < targetXLoc+width &&
- attackYLoc >= targetYLoc && attackYLoc < targetYLoc+height)
- {
- //-------------------------------------------------------//
- // the previous used range attack destination can be reused,
- // time is saved 'cos no need to check for bullet_path_possible()
- //-------------------------------------------------------//
- short bulletId = (parentUnit->attack_info_array+parentUnit->cur_attack)->bullet_sprite_id;
- Bullet* bulletPtr;
- create_bullet( bulletId, &bulletPtr);
- bulletPtr->init(BULLET_BY_UNIT, parentUnit->sprite_recno, attackXLoc, attackYLoc, UNIT_LAND);
- err_when(parentUnit->cur_dir!=parentUnit->final_dir);
- //parentUnit->get_dir(parentUnit->next_x_loc(), parentUnit->next_y_loc(), attackXLoc, attackYLoc);
- return 1;
- }
- err_here();
- return 0;
- }
- //----------- End of function BulletArray::add_bullet -----------//
- //--------- Begin of function Bullet::add_bullet ---------//
- // Overload of add_bullet()
- //
- // <Unit*> parentFirm - pointer to the attacking target Firm
- // <Unit*> targetUnit - pointer to the target Unit
- //
- // return 1 if bullet is added successfully otherwise return 0.
- short BulletArray::add_bullet(Firm* parentFirm, Unit* targetUnit)
- {
- return 0;
- }
- //----------- End of function BulletArray::add_bullet -----------//
- //--------- Begin of function Bullet::add_bullet ---------//
- // Overload of add_bullet()
- //
- // <Unit*> parentFirm - pointer to the attacking target Firm
- // <Unit*> targetFirm - pointer to the target Firm
- //
- // return 1 if bullet is added successfully otherwise return 0.
- short BulletArray::add_bullet(Firm* parentFirm, Firm* targetFirm)
- {
- return 0;
- }
- //----------- End of function BulletArray::add_bullet -----------//
|