/** * Prepare for a new turn. */ void BattleUnit::prepareNewTurn() { // recover TUs int TURecovery = _unit->getTimeUnits(); // Each fatal wound to the left or right leg reduces the soldier's TUs by 10%. TURecovery -= (TURecovery * (_fatalWounds[BODYPART_LEFTLEG]+_fatalWounds[BODYPART_RIGHTLEG] * 10))/100; setTimeUnits(TURecovery); // recover energy if (!isOut()) { int ENRecovery = _unit->getTimeUnits() / 3; // Each fatal wound to the body reduces the soldier's energy recovery by 10%. ENRecovery -= (_energy * (_fatalWounds[BODYPART_TORSO] * 10))/100; _energy += ENRecovery; if (_energy > _unit->getStamina()) _energy = _unit->getStamina(); } // suffer from fatal wounds _health -= getFatalWounds(); // suffer from fire if (_fire > 0) { _health -= RNG::generate(5, 10); _fire--; } if (_health < 0) _health = 0; // recover stun 1pt/turn if (_stunlevel > 0) stun(-1); if (!isOut()) { int chance = 100 - (2 * getMorale()); if (RNG::generate(1,100) <= chance) { int type = RNG::generate(0,100); _status = (type<=33?STATUS_BERSERK:STATUS_PANICKING); // 33% chance of berserk, panic can mean freeze or flee, but that is determined later } else { // succesfully avoided panic // increase bravery experience counter if (chance > 1) _expBravery++; } } _dontReselect = false; }
/** * Gets the response from the STUN server, checks it for its validity and * then parses the answer into address and port * \return "" if the address could be parsed or an error message */ std::string GetPublicAddress::parseStunResponse() { TransportAddress sender; const int LEN = 2048; char buffer[LEN]; int len = m_transaction_host->receiveRawPacket(buffer, LEN, &sender, 2000); if(sender.getIP()!=m_stun_server_ip) { TransportAddress stun(m_stun_server_ip, m_stun_server_port); Log::warn("GetPublicAddress", "Received stun response from %s instead of %s.", sender.toString().c_str(), stun.toString().c_str()); } if (len<0) return "STUN response contains no data at all"; // Convert to network string. NetworkString datas((uint8_t*)buffer, len); // check that the stun response is a response, contains the magic cookie // and the transaction ID if (datas.getUInt16() != 0x0101) return "STUN response doesn't contain the magic cookie"; int message_size = datas.getUInt16(); if (datas.getUInt32() != m_stun_magic_cookie) { return "STUN response doesn't contain the magic cookie"; } for (int i = 0; i < 12; i++) { if (datas.getUInt8() != m_stun_tansaction_id[i]) return "STUN response doesn't contain the transaction ID"; } Log::debug("GetPublicAddress", "The STUN server responded with a valid answer"); // The stun message is valid, so we parse it now: if (message_size == 0) return "STUN response does not contain any information."; if (message_size < 4) // cannot even read the size return "STUN response is too short."; // Those are the port and the address to be detected int pos = 20; while (true) { int type = datas.getUInt16(); int size = datas.getUInt16(); if (type == 0 || type == 1) { assert(size == 8); datas.getUInt8(); // skip 1 byte assert(datas.getUInt8() == 0x01); // Family IPv4 only uint16_t port = datas.getUInt16(); uint32_t ip = datas.getUInt32(); TransportAddress address(ip, port); // finished parsing, we know our public transport address Log::debug("GetPublicAddress", "The public address has been found: %s", address.toString().c_str()); NetworkConfig::get()->setMyAddress(address); break; } // type = 0 or 1 datas.skip(4 + size); message_size -= 4 + size; if (message_size == 0) return "STUN response is invalid."; if (message_size < 4) // cannot even read the size return "STUN response is invalid."; } // while true return ""; } // parseStunResponse