/** @file /world/units/unit.cpp Implementace hlavickoveho souboru /world/units/unit.h @author Petr Wolf */ #include "world/typedefs.h" #include "world/buildings/building.h" #include "world/world.h" using namespace World; using namespace std; World::TUnit::TUnit() { } World::TUnit::TUnit(UNIT * data, int id) : TStructHolder(data, id) { } void World::TUnit::readFromTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; interpreter.getVar(TCL_path(_path, varName, "type"), TVT_INT, &_data->type); interpreter.getVar(TCL_path(_path, varName, "max_points_of_movement"), TVT_INT, &_data->max_points_of_movement); interpreter.getArray(TCL_path(_path, varName, "movement_elevation"), TVT_FLOAT, ELEVATION_TYPES_COUNT, &_data->movement_elevation); interpreter.getArray(TCL_path(_path, varName, "movement_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->movement_terrain); interpreter.getArray(TCL_path(_path, varName, "movement_weather"), TVT_FLOAT, WEATHER_STATES_COUNT, &_data->movement_weather); interpreter.getVar(TCL_path(_path, varName, "movement_uphill"), TVT_FLOAT, &_data->movement_uphill); interpreter.getVar(TCL_path(_path, varName, "movement_downhill"), TVT_FLOAT, &_data->movement_downhill); interpreter.getVar(TCL_path(_path, varName, "can_enter_building"), TVT_INT, &_data->can_enter_building); interpreter.getVar(TCL_path(_path, varName, "attack"), TVT_INT, &_data->attack); interpreter.getVar(TCL_path(_path, varName, "defense"), TVT_INT, &_data->defense); interpreter.getVar(TCL_path(_path, varName, "counterattack"), TVT_INT, &_data->counterattack); interpreter.getVar(TCL_path(_path, varName, "movement_and_fight_combination"), TVT_INT, &_data->movement_and_fight_combination); interpreter.getVar(TCL_path(_path, varName, "fight_type"), TVT_INT, &_data->fight_type); interpreter.getArray(TCL_path(_path, varName, "attack_bonus_from_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->attack_bonus_from_terrain); interpreter.getArray(TCL_path(_path, varName, "defense_bonus_from_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->defense_bonus_from_terrain); interpreter.getArray(TCL_path(_path, varName, "attack_bonus_against_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->attack_bonus_against_terrain); interpreter.getArray(TCL_path(_path, varName, "attack_bonus_against_unit"), TVT_FLOAT, UNIT_TYPES_COUNT, &_data->attack_bonus_against_unit); interpreter.getVar(TCL_path(_path, varName, "attack_bonus_against_building"), TVT_FLOAT, &_data->attack_bonus_against_building); interpreter.getVar(TCL_path(_path, varName, "attack_range"), TVT_INT, &_data->attack_range); interpreter.getVar(TCL_path(_path, varName, "hit_probability"), TVT_FLOAT, &_data->hit_probability); interpreter.getVar(TCL_path(_path, varName, "default_occurrence"), TVT_INT, &_data->default_occurrence); interpreter.getVar(TCL_path(_path, varName, "cost"), TVT_INT, &_data->cost); interpreter.getVar(TCL_path(_path, varName, "pay"), TVT_INT, &_data->pay); interpreter.getVar(TCL_path(_path, varName, "max_lives"), TVT_INT, &_data->max_lives); interpreter.getVar(TCL_path(_path, varName, "cure_cost"), TVT_INT, &_data->cure_cost); interpreter.getVar(TCL_path(_path, varName, "eyesight_distance"), TVT_INT, &_data->eyesight_distance); interpreter.getVar(TCL_path(_path, varName, "can_build_building"), TVT_INT, &_data->can_build_building); interpreter.getArray(TCL_path(_path, varName, "bonuses"), TVT_INT, UNIT_PROPERTY_COUNT, &_data->bonuses); } void World::TUnit::writeToTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; interpreter.setVar(TCL_path(_path, varName, "type"), TVT_INT, &_data->type); interpreter.setVar(TCL_path(_path, varName, "max_points_of_movement"), TVT_INT, &_data->max_points_of_movement); interpreter.setArray(TCL_path(_path, varName, "movement_elevation"), TVT_FLOAT, ELEVATION_TYPES_COUNT, &_data->movement_elevation); interpreter.setArray(TCL_path(_path, varName, "movement_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->movement_terrain); interpreter.setArray(TCL_path(_path, varName, "movement_weather"), TVT_FLOAT, WEATHER_STATES_COUNT, &_data->movement_weather); interpreter.setVar(TCL_path(_path, varName, "movement_uphill"), TVT_FLOAT, &_data->movement_uphill); interpreter.setVar(TCL_path(_path, varName, "movement_downhill"), TVT_FLOAT, &_data->movement_downhill); interpreter.setVar(TCL_path(_path, varName, "can_enter_building"), TVT_INT, &_data->can_enter_building); interpreter.setVar(TCL_path(_path, varName, "attack"), TVT_INT, &_data->attack); interpreter.setVar(TCL_path(_path, varName, "defense"), TVT_INT, &_data->defense); interpreter.setVar(TCL_path(_path, varName, "counterattack"), TVT_INT, &_data->counterattack); interpreter.setVar(TCL_path(_path, varName, "movement_and_fight_combination"), TVT_INT, &_data->movement_and_fight_combination); interpreter.setVar(TCL_path(_path, varName, "fight_type"), TVT_INT, &_data->fight_type); interpreter.setArray(TCL_path(_path, varName, "attack_bonus_from_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->attack_bonus_from_terrain); interpreter.setArray(TCL_path(_path, varName, "defense_bonus_from_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->defense_bonus_from_terrain); interpreter.setArray(TCL_path(_path, varName, "attack_bonus_against_terrain"), TVT_FLOAT, TERRAIN_TYPES_COUNT + 1, &_data->attack_bonus_against_terrain); interpreter.setArray(TCL_path(_path, varName, "attack_bonus_against_unit"), TVT_FLOAT, UNIT_TYPES_COUNT, &_data->attack_bonus_against_unit); interpreter.setVar(TCL_path(_path, varName, "attack_bonus_against_building"), TVT_FLOAT, &_data->attack_bonus_against_building); interpreter.setVar(TCL_path(_path, varName, "attack_range"), TVT_INT, &_data->attack_range); interpreter.setVar(TCL_path(_path, varName, "hit_probability"), TVT_FLOAT, &_data->hit_probability); interpreter.setVar(TCL_path(_path, varName, "default_occurrence"), TVT_INT, &_data->default_occurrence); interpreter.setVar(TCL_path(_path, varName, "cost"), TVT_INT, &_data->cost); interpreter.setVar(TCL_path(_path, varName, "pay"), TVT_INT, &_data->pay); interpreter.setVar(TCL_path(_path, varName, "max_lives"), TVT_INT, &_data->max_lives); interpreter.setVar(TCL_path(_path, varName, "cure_cost"), TVT_INT, &_data->cure_cost); interpreter.setVar(TCL_path(_path, varName, "eyesight_distance"), TVT_INT, &_data->eyesight_distance); interpreter.setVar(TCL_path(_path, varName, "can_build_building"), TVT_INT, &_data->can_build_building); interpreter.setArray(TCL_path(_path, varName, "bonuses"), TVT_INT, UNIT_PROPERTY_COUNT, &_data->bonuses); } TBonus::TBonus() { } TBonus::TBonus(UNIT_PROPERTY_BONUS * data, int id) : TStructHolder(data, id) { } void TBonus::readFromTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; interpreter.getVar(TCL_path(_path, varName, "property"), TVT_INT, &_data->property); interpreter.getVar(TCL_path(_path, varName, "cost"), TVT_INT, &_data->cost); interpreter.getVar(TCL_path(_path, varName, "bonus"), TVT_INT, &_data->bonus); } void TBonus::writeToTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; interpreter.setVar(TCL_path(_path, varName, "property"), TVT_INT, &_data->property); interpreter.setVar(TCL_path(_path, varName, "cost"), TVT_INT, &_data->cost); interpreter.setVar(TCL_path(_path, varName, "bonus"), TVT_INT, &_data->bonus); } TLivingUnit::TLivingUnit() { _hex = 0; _building = 0; } TLivingUnit::TLivingUnit(LIVING_UNIT * data, int id) : TStructHolder(data, id) { _hex = 0; _building = 0; } TLivingUnit::TLivingUnit(int id) : TStructHolder(id) { _hex = 0; _building = 0; } TLivingUnit::~TLivingUnit() { if (_data && _self_allocated) { KMemFree(_data->bonuses.data); } } void TLivingUnit::readFromXML(TPackage * package) { if (_data == NULL) { alloc(); LIVING_UNIT_Init(_data); } _data->type = package->getInt("type", 0, NULL); _data->player = package->getInt("player", 0, NULL); _data->state = (UNIT_STATE)package->getInt("state", 0, NULL); package->getChar(_data->name, MAX_STRLEN, "name", 0, NULL); _data->lives = package->getInt("lives", 0, NULL); _data->assaults_count = package->getInt("assaults_count", 0, NULL); _data->points_of_movement = package->getInt("points_of_movement", 0, NULL); _data->level = package->getInt("level", 0, NULL); _data->experience = package->getInt("experience", 0, NULL); _data->orientation = package->getInt("orientation", 0, NULL); INT_ARRAY_FROM_XML(package, &_data->bonuses.data, &_data->bonuses.length, "bonuses"); INT_ARRAY_FROM_XML(package, _data->wounds, MAX_LIVES, "wounds"); } void TLivingUnit::writeToXML(TPackage * package) { package->setInt(_data->type, "type", 0, NULL); package->setInt(_data->player, "player", 0, NULL); package->setInt(_data->state, "state", 0, NULL); package->setChar(_data->name, "name", 0, NULL); package->setInt(_data->lives, "lives", 0, NULL); package->setInt(_data->assaults_count, "assaults_count", 0, NULL); package->setInt(_data->points_of_movement, "points_of_movement", 0, NULL); package->setInt(_data->level, "level", 0, NULL); package->setInt(_data->experience, "experience", 0, NULL); package->setInt(_data->orientation, "orientation", 0, NULL); INT_ARRAY_TO_XML(package, _data->bonuses.data, _data->bonuses.length, "bonuses"); INT_ARRAY_TO_XML(package, _data->wounds, MAX_LIVES, "wounds"); } void TLivingUnit::readFromTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; interpreter.getVar(TCL_path(_path, varName, "type"), TVT_INT, &_data->type); interpreter.getVar(TCL_path(_path, varName, "player"), TVT_INT, &_data->player); interpreter.getVar(TCL_path(_path, varName, "state"), TVT_INT, &_data->state); interpreter.getVar(TCL_path(_path, varName, "lives"), TVT_INT, &_data->lives); interpreter.getVar(TCL_path(_path, varName, "assaults_count"), TVT_INT, &_data->assaults_count); interpreter.getVar(TCL_path(_path, varName, "points_of_movement"), TVT_INT, &_data->points_of_movement); interpreter.getVar(TCL_path(_path, varName, "level"), TVT_INT, &_data->level); interpreter.getVar(TCL_path(_path, varName, "experience"), TVT_INT, &_data->experience); interpreter.getVar(TCL_path(_path, varName, "building"), TVT_INT, &_building); interpreter.getArray(TCL_path(_path, varName, "bonuses"), TVT_INT, _data->bonuses.length, &_data->bonuses.data); interpreter.getArray(TCL_path(_path, varName, "wounds"), TVT_INT, MAX_LIVES, &_data->wounds); } void TLivingUnit::writeToTCL(TTCL_Interpreter & interpreter, const char * varName) { char _path[MAX_STRLEN]; int temp; // jednoduche polozky interpreter.setVar(TCL_path(_path, varName, "type"), TVT_INT, &_data->type); interpreter.setVar(TCL_path(_path, varName, "player"), TVT_INT, &_data->player); interpreter.setVar(TCL_path(_path, varName, "state"), TVT_INT, &_data->state); interpreter.setVar(TCL_path(_path, varName, "lives"), TVT_INT, &_data->lives); interpreter.setVar(TCL_path(_path, varName, "assaults_count"), TVT_INT, &_data->assaults_count); interpreter.setVar(TCL_path(_path, varName, "points_of_movement"), TVT_INT, &_data->points_of_movement); interpreter.setVar(TCL_path(_path, varName, "level"), TVT_INT, &_data->level); interpreter.setVar(TCL_path(_path, varName, "experience"), TVT_INT, &_data->experience); interpreter.setVar(TCL_path(_path, varName, "building"), TVT_INT, &_building); // pole interpreter.setArray(TCL_path(_path, varName, "bonuses"), TVT_INT, _data->bonuses.length, _data->bonuses.data); interpreter.setArray(TCL_path(_path, varName, "wounds"), TVT_INT, _data->lives, _data->wounds); // read-only vlastnosti interpreter.setVar(TCL_path(_path, varName, "hex"), TVT_INT, &_hex); temp = attackBonus(); interpreter.setVar(TCL_path(_path, varName, "attack_bonus"), TVT_INT, &temp); temp = defenseBonus(); interpreter.setVar(TCL_path(_path, varName, "defense_bonus"), TVT_INT, &temp); temp = maxLivesBonus(); interpreter.setVar(TCL_path(_path, varName, "lives_bonus"), TVT_INT, &temp); temp = attackRangeBonus(); interpreter.setVar(TCL_path(_path, varName, "range_bonus"), TVT_INT, &temp); temp = movementPointsBonus(); interpreter.setVar(TCL_path(_path, varName, "movement_bonus"), TVT_INT, &temp); } BUILDING_ID TLivingUnit::building() { return _building; } TLivingBuilding * TLivingUnit::tBuilding() { if (_building) return _world->buildings[_building]; else return NULL; } HEX_ID TLivingUnit::hex() { return _hex; } THex * TLivingUnit::tHex() { if (_hex) return _world->map.getHexById(_hex); else return NULL; } bool TLivingUnit::isOperational() { switch (_data->state) { case US_IDLE: case US_BUILDING: return true; case US_EXHAUSTED: case US_HAS_STARTED_BUILDING: return false; case US_HAS_FOUGHT_AND_MOVED: return (_data->points_of_movement > 0); case US_HAS_MOVED: return ( (_data->points_of_movement > 0) || (_world->rules->unit_types[_data->type]->data().movement_and_fight_combination == MFC_MOVEMENT_FIRST) || (_world->rules->unit_types[_data->type]->data().movement_and_fight_combination == MFC_ANYTHING) ); case US_HAS_FOUGHT: return ( (_data->points_of_movement > 0) && ( (_world->rules->unit_types[_data->type]->data().movement_and_fight_combination == MFC_ATTACK_FIRST) || (_world->rules->unit_types[_data->type]->data().movement_and_fight_combination == MFC_ANYTHING) ) ); } return true; } int TLivingUnit::attackBonus() { int result = 0; for (int i = 0; i < _data->bonuses.length; i++) { if (_world->rules->bonus_types[_data->bonuses.data[i]]->data().property == UP_ATTACK) result += _world->rules->bonus_types[_data->bonuses.data[i]]->data().bonus; } return result; } int TLivingUnit::defenseBonus() { int result = 0; for (int i = 0; i < _data->bonuses.length; i++) { if (_world->rules->bonus_types[_data->bonuses.data[i]]->data().property == UP_DEFENSE) result += _world->rules->bonus_types[_data->bonuses.data[i]]->data().bonus; } return result; } int TLivingUnit::maxLivesBonus() { int result = 0; for (int i = 0; i < _data->bonuses.length; i++) { if (_world->rules->bonus_types[_data->bonuses.data[i]]->data().property == UP_LIVES) result += _world->rules->bonus_types[_data->bonuses.data[i]]->data().bonus; } return result; } int TLivingUnit::movementPointsBonus() { int result = 0; for (int i = 0; i < _data->bonuses.length; i++) { if (_world->rules->bonus_types[_data->bonuses.data[i]]->data().property == UP_MOVEMENT) result += _world->rules->bonus_types[_data->bonuses.data[i]]->data().bonus; } return result; } int TLivingUnit::attackRangeBonus() { int result = 0; for (int i = 0; i < _data->bonuses.length; i++) { if (_world->rules->bonus_types[_data->bonuses.data[i]]->data().property == UP_ATTACK_RANGE) result += _world->rules->bonus_types[_data->bonuses.data[i]]->data().bonus; } return result; }