/*
* 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 .
*
*/
//Filename : OTORNADO.CPP
//Description : Object Tornado
//Ownership : Gilbert
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define M_PI 3.141592654
#define DAMAGE_POINT_RADIUS 32
#define TORNADO_SPRITE_ID 12 // Tornado sprite in SPRITE.DBF
//--------- Begin of function Tornado::init ---------//
//
// startX, startY starting location of the tornado
// lifeTime time (no. of frames) the tornado survive
//
void Tornado::init(short startX, short startY, short lifeTime)
{
Sprite::init(TORNADO_SPRITE_ID, startX, startY);
err_when( strcmp("TORNADO", sprite_info->sprite_code ) );
attack_damage = (float) 2.0 / ATTACK_SLOW_DOWN;
life_time = lifeTime;
set_dir(DIR_N);
cur_action = SPRITE_MOVE; // always moving
dmg_offset_x = 0;
dmg_offset_y = 0;
}
//----------- End of function Tornado::init -----------//
//----------- Begin of function Tornado::pre_process ----------//
void Tornado::pre_process()
{
double angle = m.random(32) / 16.0 * M_PI;
dmg_offset_x = short(DAMAGE_POINT_RADIUS * sin(angle));
dmg_offset_y = short(DAMAGE_POINT_RADIUS * cos(angle));
if( --life_time <= 0)
cur_action = SPRITE_DIE;
}
//----------- End of function Tornado::pre_process ----------//
//--------- Begin of function Tornado::process_move --------//
void Tornado::process_move()
{
int speed = weather.wind_speed() / 6;
int minSpeed = magic_weather.wind_day > 0 ? 1 : 5;
if( speed < minSpeed)
speed = minSpeed;
if( speed > 10)
speed = 10;
double windDir = weather.wind_direct_rad() + (m.random(31)-15)*M_PI/180.0;
cur_x += short(speed * sin(windDir));
cur_y -= short(speed * cos(windDir));
if( ++cur_frame > cur_sprite_move()->frame_count )
cur_frame = 1;
// static UCHAR nextFrame[] = { 1,6,1,1,1,1,4 }; // 1->6->4->1 ...
// cur_frame = nextFrame[cur_frame];
hit_target();
}
//---------- End of function Tornado::process_move ----------//
//--------- Begin of function Tornado::hit_target --------//
void Tornado::hit_target()
{
//---- check if there is any unit in the target location ----//
short damageXLoc = damage_x_loc();
short damageYLoc = damage_y_loc();
if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
damageYLoc < 0 || damageYLoc >= world.max_y_loc)
return;
Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
Unit *targetUnit;
if( locPtr->has_unit(UNIT_AIR))
{
targetUnit = unit_array[locPtr->unit_recno(UNIT_AIR)];
targetUnit->hit_points -= 2*attack_damage;
if( targetUnit->hit_points <= 0)
targetUnit->hit_points = (float) 0;
}
if( locPtr->has_unit(UNIT_LAND))
{
targetUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
targetUnit->hit_points -= attack_damage;
if( targetUnit->hit_points <= 0)
targetUnit->hit_points = (float) 0;
}
else if( locPtr->has_unit(UNIT_SEA))
{
targetUnit = unit_array[locPtr->unit_recno(UNIT_SEA)];
targetUnit->hit_points -= attack_damage;
if( targetUnit->hit_points <= 0)
targetUnit->hit_points = (float) 0;
}
else
{
hit_building(); // pass to hit_building to check whether a building is in the location
}
hit_plant();
hit_fire();
}
//---------- End of function Tornado::hit_target ----------//
//------- Begin of function Tornado::hit_building -----//
// building means firm or town
//
void Tornado::hit_building()
{
short damageXLoc = damage_x_loc();
short damageYLoc = damage_y_loc();
if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
damageYLoc < 0 || damageYLoc >= world.max_y_loc)
return;
Location* locPtr = world.get_loc(damageXLoc, damageYLoc);
// ##### begin Gilbert 30/10 #####//
if(locPtr->is_firm() )
// && firm_res[(firmPtr=firm_array[locPtr->firm_recno()])->firm_id]->buildable )
{
Firm *firmPtr = firm_array[locPtr->firm_recno()];
firmPtr->hit_points -= attack_damage*2;
if( firmPtr->hit_points <= 0)
{
firmPtr->hit_points = (float) 0;
se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
'F', firmPtr->firm_id, "DIE" );
firm_array.del_firm(locPtr->firm_recno());
}
}
if( locPtr->is_town() )
{
Town *townPtr = town_array[locPtr->town_recno()];
if( (life_time % 30) == 0 )
townPtr->kill_town_people(0);
}
// ##### end Gilbert 30/10 #####//
}
//---------- End of function Tornado::hit_building ----------//
//---------- Begin of function Tornado::hit_plant --------//
void Tornado::hit_plant()
{
short damageXLoc = damage_x_loc();
short damageYLoc = damage_y_loc();
if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
damageYLoc < 0 || damageYLoc >= world.max_y_loc)
return;
Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
if(locPtr->is_plant())
{
locPtr->remove_plant();
// ###### begin Gilbert 24/6 ########//
world.plant_count--;
// ###### end Gilbert 24/6 ########//
}
}
//---------- End of function Tornado::hit_plant --------//
//---------- Begin of function Tornado::hit_fire --------//
void Tornado::hit_fire()
{
short damageXLoc = damage_x_loc();
short damageYLoc = damage_y_loc();
if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
damageYLoc < 0 || damageYLoc >= world.max_y_loc)
return;
Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
if(locPtr->fire_str() > 0)
{
locPtr->set_fire_str(1);
}
}
//---------- End of function Tornado::hit_plant --------//
#ifdef DEBUG
//------- Begin of function TornadoArray::operator[] -----//
Tornado* TornadoArray::operator[](int recNo)
{
Tornado* tornadoPtr = (Tornado*) get_ptr(recNo);
if( !tornadoPtr )
err.run( "TornadoArray[] is deleted" );
return tornadoPtr;
}
//--------- End of function TornadoArray::operator[] ----//
#endif
//--------- Begin of function TornadoArray::TornadoArray ------//
TornadoArray::TornadoArray(int initArraySize): SpriteArray(initArraySize)
{
}
//--------- End of function TornadoArray::TornadoArray ------//
//--------- Begin of function TornadoArray::add_tornado ------//
//
// startX, startY starting location of the tornado
// lifeTime time (no. of frames) the tornado survive
//
short TornadoArray::add_tornado(int xLoc, int yLoc, short lifeTime)
{
Tornado *tornadoPtr = new Tornado;
tornadoPtr->init(xLoc, yLoc, lifeTime);
add(tornadoPtr);
return 1;
}
//--------- End of function TornadoArray::add_tornado ------//
//--------- Begin of function TornadoArray::create_tornado ------//
//
// return: recno of the tornado created.
//
short TornadoArray::create_tornado()
{
Tornado *tornadoPtr = new Tornado;
add(tornadoPtr);
return recno();
}
//--------- End of function TornadoArray::create_tornado ------//
//--------- Begin of function TornadoArray::process ---------//
void TornadoArray::process()
{
int i;
Tornado* tornadoPtr;
for (i=1; i <=size() ; i++)
{
tornadoPtr = (Tornado*)get_ptr(i);
if( !tornadoPtr)
continue;
//-------- system yield ---------//
if( i%20==1 )
sys.yield();
//------- process tornado --------//
tornadoPtr->pre_process();
switch(tornadoPtr->cur_action)
{
case SPRITE_IDLE:
case SPRITE_READY_TO_MOVE:
tornadoPtr->process_idle();
break;
case SPRITE_MOVE:
tornadoPtr->process_move();
break;
//### begin alex 7/3 ###//
case SPRITE_TURN:
err_here();
break;
//#### end alex 7/3 ####//
case SPRITE_WAIT:
tornadoPtr->process_wait();
break;
case SPRITE_ATTACK:
tornadoPtr->process_attack();
break;
case SPRITE_DIE:
if( tornadoPtr->process_die() )
del(i);
break;
}
}
}
//----------- End of function TornadoArray::process -----------//
//--------- Begin of function TornadoArray::draw_dot ---------//
//
// Draw 2x2 tiny squares on map window representing the location of the unit ---//
//
void TornadoArray::draw_dot()
{
char* vgaBufPtr = vga_back.buf_ptr();
char* writePtr;
Tornado* tornadoPtr;
int i, mapX, mapY;
int vgaBufPitch = vga_back.buf_pitch();
for(i=1; i <=size() ; i++)
{
tornadoPtr = (Tornado*)get_ptr(i);
if( !tornadoPtr )
continue;
mapX = MAP_X1 + tornadoPtr->cur_x_loc();
mapY = MAP_Y1 + tornadoPtr->cur_y_loc();
// ####### begin Gilbert 13/11 #########//
if( mapX < MAP_X1 || mapX > MAP_X2 || mapY < MAP_Y1 || mapY > MAP_Y2 )
return;
// ####### end Gilbert 13/11 #########//
writePtr = vgaBufPtr + mapY*vgaBufPitch + mapX;
if( mapY > MAP_Y1)
{
if( mapX > MAP_X1 && writePtr[-vgaBufPitch-1] != UNEXPLORED_COLOR)
writePtr[-vgaBufPitch-1] = (char)TORNADO_COLOR2;
if( writePtr[-vgaBufPitch] != UNEXPLORED_COLOR)
writePtr[-vgaBufPitch] = (char)TORNADO_COLOR1;
if( mapX < MAP_X2 && writePtr[-vgaBufPitch+1] != UNEXPLORED_COLOR)
writePtr[-vgaBufPitch+1] = (char)TORNADO_COLOR2;
}
if( mapX > MAP_X1 && writePtr[-1] != UNEXPLORED_COLOR)
writePtr[-1] = (char)TORNADO_COLOR1;
if( mapX < MAP_X2 && writePtr[1] != UNEXPLORED_COLOR)
writePtr[1] = (char)TORNADO_COLOR1;
if( mapY < MAP_Y2)
{
if( mapX > MAP_X1 && writePtr[vgaBufPitch-1] != UNEXPLORED_COLOR)
writePtr[vgaBufPitch-1] = (char)TORNADO_COLOR2;
if( writePtr[vgaBufPitch] != UNEXPLORED_COLOR)
writePtr[vgaBufPitch] = (char)TORNADO_COLOR1;
if( mapX < MAP_X2 && writePtr[vgaBufPitch+1] != UNEXPLORED_COLOR)
writePtr[vgaBufPitch+1] = (char)TORNADO_COLOR2;
}
}
}
//----------- End of function UnitArray::draw_dot -----------//