Skip to content

Commit 89cbbfc

Browse files
committed
1. Improved research sync, the other player now gets the same research popup, and research projects update instantly without needing to reload a save.
2. Added base facility sync, when one player builds or removes a facility, the change updates instantly for the other player when viewing that base. No need to go to the Geoscape and back to see the changes. 3. Alien base markers are now synced on the Geoscape. 4. Fixed mission sites on the Geoscape, they should no longer disappear for the other player. 5. If a player shoots down a UFO over water, it is now destroyed on impact and will not crash and create a mission. 6. Fixed a Battlescape sync issue where throwing an item could sometimes end up on the wrong tile. 7. Improved tile damage sync so tiles like walls and doors now get destroyed in exactly the same way on both players. Before, if you fired a rocket and it hit a wall, the damage could be different for the other player, would not sync, and could break pathfinding. 8. Fixed an issue where a soldier sometimes would not shoot while berserk. 9. Fixed soldiers disappearing in the new battle menu after ending a mission. 10. If you lose a base defense mission, it no longer counts the other player’s base, so the game will not continue if you lose your last base. 11. Units that are on fire should now sync in Battlescape, tested with The X-Com Files. 12. Fixed Battlescape sync issues when a unit was turning or opening a door. 13. Other small fixes and improvements.
1 parent 8c6c685 commit 89cbbfc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1416
-465
lines changed

src/Basescape/BaseView.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ void BaseView::resetSelectedFacility()
150150
_selFacility = 0;
151151
}
152152

153+
void BaseView::resetSelectedFacilityCoop(int fac_x, int fac_y)
154+
{
155+
_facilities[fac_x][fac_y] = 0;
156+
_selFacility = 0;
157+
}
153158

154159
/**
155160
* Returns the X position of the grid square

src/Basescape/BaseView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class BaseView : public InteractiveSurface
7272
BaseFacility *getSelectedFacility() const;
7373
/// Prevents any mouseover bugs on dismantling base facilities before setBase has had time to update the base.
7474
void resetSelectedFacility();
75+
// coop
76+
void resetSelectedFacilityCoop(int fac_x, int fac_y);
7577
/// Gets the X position of the currently selected square.
7678
int getGridX() const;
7779
/// Gets the Y position of the currently selected square.

src/Basescape/BasescapeState.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include "../Menu/LoadGameState.h"
6363
#include "CraftSoldiersState.h"
6464
#include "../Savegame/Vehicle.h"
65+
#include "../Engine/Sound.h"
6566

6667
namespace OpenXcom
6768
{
@@ -353,6 +354,130 @@ void BasescapeState::init()
353354

354355

355356

357+
}
358+
359+
void BasescapeState::think()
360+
{
361+
362+
// coop
363+
if (_game->getCoopMod()->getCoopStatic() == true)
364+
{
365+
366+
Json::Value& arr = _game->getCoopMod()->_coopFacility;
367+
if (!arr.empty())
368+
{
369+
Json::Value str_fac = arr[0];
370+
371+
double base_lat = str_fac["base_lat"].asDouble();
372+
double base_lon = str_fac["base_lon"].asDouble();
373+
374+
if (_base->getLatitude() == base_lat && _base->getLongitude() == base_lon)
375+
{
376+
377+
std::string rule = str_fac["rule"].asString();
378+
int fac_x = str_fac["fac_x"].asInt();
379+
int fac_y = str_fac["fac_y"].asInt();
380+
int build_time = str_fac["build_time"].asInt();
381+
bool buildingOver = str_fac["buildingOver"].asBool();
382+
int build_cost = str_fac["build_cost"].asInt();
383+
384+
RuleBaseFacility* facilityRule = _game->getMod()->getBaseFacility(rule);
385+
386+
if (facilityRule)
387+
{
388+
389+
BaseFacility* fac = new BaseFacility(facilityRule, _base);
390+
fac->setX(fac_x);
391+
fac->setY(fac_y);
392+
fac->setBuildTime(build_time);
393+
if (buildingOver)
394+
{
395+
fac->setIfHadPreviousFacility(true);
396+
}
397+
_base->getFacilities()->push_back(fac);
398+
if (fac->getRules()->getPlaceSound() != Mod::NO_SOUND)
399+
{
400+
_game->getMod()->getSound("GEO.CAT", fac->getRules()->getPlaceSound())->play();
401+
}
402+
if (Options::allowBuildingQueue)
403+
{
404+
if (_view->isQueuedBuilding(facilityRule))
405+
fac->setBuildTime(INT_MAX);
406+
_view->reCalcQueuedBuildings();
407+
}
408+
_view->setBase(_base);
409+
_game->getSavedGame()->setFunds(_game->getSavedGame()->getFunds() - build_cost);
410+
}
411+
412+
arr.removeIndex(0, nullptr);
413+
414+
}
415+
else if (_game->getCoopMod()->playerInsideCoopBase == false)
416+
{
417+
arr.removeIndex(0, nullptr);
418+
}
419+
420+
}
421+
422+
}
423+
424+
// COOP
425+
if (_game->getCoopMod()->getCoopStatic() == true)
426+
{
427+
428+
Json::Value& arr = _game->getCoopMod()->_deleteCoopFacility;
429+
430+
// Make sure all facilities are built before removing anything
431+
Json::Value& arr2 = _game->getCoopMod()->_coopFacility;
432+
433+
if (!arr.empty() && arr2.empty())
434+
{
435+
436+
Json::Value str_fac = arr[0];
437+
438+
double base_lat = str_fac["base_lat"].asDouble();
439+
double base_lon = str_fac["base_lon"].asDouble();
440+
441+
if (_base->getLatitude() == base_lat && _base->getLongitude() == base_lon)
442+
{
443+
444+
int fac_x = str_fac["fac_x"].asInt();
445+
int fac_y = str_fac["fac_y"].asInt();
446+
447+
auto* facilities = _base->getFacilities();
448+
449+
for (auto it = facilities->begin(); it != facilities->end();)
450+
{
451+
auto* fac = *it;
452+
453+
if (fac->getX() == fac_x && fac->getY() == fac_y)
454+
{
455+
it = facilities->erase(it);
456+
_view->resetSelectedFacilityCoop(fac_x, fac_y);
457+
delete fac;
458+
_view->setBase(_base);
459+
if (Options::allowBuildingQueue)
460+
_view->reCalcQueuedBuildings();
461+
break;
462+
}
463+
else
464+
{
465+
++it;
466+
}
467+
}
468+
469+
arr.removeIndex(0, nullptr);
470+
}
471+
else if (_game->getCoopMod()->playerInsideCoopBase == false)
472+
{
473+
arr.removeIndex(0, nullptr);
474+
}
475+
476+
}
477+
478+
479+
}
480+
356481
}
357482

358483
/**

src/Basescape/BasescapeState.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class BasescapeState : public State
5151
~BasescapeState();
5252
/// Updates the base stats.
5353
void init() override;
54+
/// Runs the timers and handles popups.
55+
void think() override;
5456
/// Sets a new base to display.
5557
void setBase(Base *base);
5658
/// Handler for clicking the Build New Base button.

src/Basescape/DismantleFacilityState.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@ void DismantleFacilityState::btnOkClick(Action *)
160160
{
161161
if (*facIt == _fac)
162162
{
163+
164+
// COOP
165+
if (_game->getCoopMod()->getCoopStatic() == true && _base->_coopBase == false && _game->getCoopMod()->playerInsideCoopBase == false)
166+
{
167+
168+
Json::Value root;
169+
root["state"] = "dismantle_facility";
170+
171+
root["base_lat"] = _base->getLatitude();
172+
root["base_lon"] = _base->getLongitude();
173+
root["fac_x"] = _fac->getX();
174+
root["fac_y"] = _fac->getY();
175+
176+
_game->getCoopMod()->sendTCPPacketData(root.toStyledString());
177+
}
178+
163179
_base->getFacilities()->erase(facIt);
164180
// Determine if we leave behind any facilities when this one is removed
165181
if (_fac->getBuildTime() == 0 && _fac->getRules()->getLeavesBehindOnSell().size() != 0)

src/Basescape/PlaceFacilityState.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,27 @@ void PlaceFacilityState::viewClick(Action *)
387387
{
388388
_game->popState();
389389
}
390+
391+
// COOP
392+
if (_game->getCoopMod()->getCoopStatic() == true && _base->_coopBase == false && _game->getCoopMod()->playerInsideCoopBase == false)
393+
{
394+
395+
Json::Value root;
396+
root["state"] = "place_facility";
397+
398+
root["base_lat"] = _base->getLatitude();
399+
root["base_lon"] = _base->getLongitude();
400+
root["rule"] = _rule->getType();
401+
root["fac_x"] = fac->getX();
402+
root["fac_y"] = fac->getY();
403+
root["build_time"] = fac->getBuildTime();
404+
root["buildingOver"] = buildingOver;
405+
root["build_cost"] = _rule->getBuildCost();
406+
407+
_game->getCoopMod()->sendTCPPacketData(root.toStyledString());
408+
409+
}
410+
390411
}
391412
}
392413
}

src/Battlescape/BattlescapeGame.cpp

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,6 @@ void BattlescapeGame::movePlayerTarget(std::string obj_str)
300300
if (_save->getBattleGame()->getCoopMod()->getCoopGamemode() == 2 || _save->getBattleGame()->getCoopMod()->getCoopGamemode() == 3)
301301
{
302302

303-
if (_currentAction.run == false)
304-
{
305-
sound = false;
306-
}
307-
308303
if (_currentAction.sneak == true)
309304
{
310305
sound = false;
@@ -345,9 +340,7 @@ void BattlescapeGame::turnPlayerTarget(std::string obj_str)
345340
int endy = obj["coords"]["end"]["y"].asInt();
346341
int endz = obj["coords"]["end"]["z"].asInt();
347342

348-
349-
int setDirection = obj["setDirection"].asInt();
350-
int setFaceDirection = obj["setFaceDirection"].asInt();
343+
bool isActionTypeNone = obj["isActionTypeNone"].asBool();
351344

352345
Position *startpos = new Position(startx, starty, startz);
353346
Position *endpos = new Position(endx, endy, endz);
@@ -374,9 +367,6 @@ void BattlescapeGame::turnPlayerTarget(std::string obj_str)
374367

375368
unit->setPosition(*startpos);
376369

377-
unit->setDirection(setDirection);
378-
unit->setFaceDirection(setFaceDirection);
379-
380370
if (getCoopMod()->_isActiveAISync == false && getCoopMod()->getCoopGamemode() != 2 && getCoopMod()->getCoopGamemode() != 3)
381371
{
382372
for (auto& unit : *_save->getUnits())
@@ -407,7 +397,13 @@ void BattlescapeGame::turnPlayerTarget(std::string obj_str)
407397
// other
408398
_save->setSelectedUnit(unit);
409399
_currentAction.actor = unit;
410-
_currentAction.type = BA_WALK;
400+
_currentAction.type = BA_TURN;
401+
402+
if (isActionTypeNone == true)
403+
{
404+
_currentAction.type = BA_NONE;
405+
}
406+
411407
_currentAction.targeting = false;
412408

413409
bool isUnitAlreadyTurn = false;
@@ -423,6 +419,66 @@ void BattlescapeGame::turnPlayerTarget(std::string obj_str)
423419
{
424420
statePushFront(new UnitTurnBState(this, _currentAction));
425421
}
422+
// door fix
423+
else
424+
{
425+
426+
if (_currentAction.type == BA_NONE)
427+
{
428+
// try to open a door
429+
int door = _save->getTileEngine()->unitOpensDoor(unit, true);
430+
if (door == 0)
431+
{
432+
_save->getMod()->getSoundByDepth(_save->getDepth(), Mod::DOOR_OPEN)->play(-1, getMap()->getSoundAngle(unit->getPosition())); // normal door
433+
}
434+
if (door == 1)
435+
{
436+
_save->getMod()->getSoundByDepth(_save->getDepth(), Mod::SLIDING_DOOR_OPEN)->play(-1, getMap()->getSoundAngle(unit->getPosition())); // ufo door
437+
}
438+
if (door == 4)
439+
{
440+
_currentAction.result = "STR_NOT_ENOUGH_TIME_UNITS";
441+
}
442+
}
443+
444+
}
445+
446+
}
447+
448+
void BattlescapeGame::turnPlayerTargetAfter(std::string obj_str)
449+
{
450+
451+
Json::Reader reader;
452+
Json::Value obj;
453+
454+
reader.parse(obj_str, obj);
455+
456+
int unit_id = obj["unit_id"].asInt();
457+
int setDirection = obj["setDirection"].asInt();
458+
int setFaceDirection = obj["setFaceDirection"].asInt();
459+
460+
BattleUnit* unit = 0;
461+
462+
bool found_unit = false;
463+
464+
// unit
465+
for (auto u : *_save->getUnits())
466+
{
467+
468+
if (u->getId() == unit_id)
469+
{
470+
found_unit = true;
471+
unit = u;
472+
break;
473+
}
474+
}
475+
476+
if (found_unit == false)
477+
return;
478+
479+
unit->abortTurn();
480+
unit->setFaceDirection(setFaceDirection);
481+
unit->setDirection(setDirection);
426482

427483
}
428484

@@ -478,6 +534,9 @@ void BattlescapeGame::psi_attack(std::string obj_str)
478534
}
479535
}
480536

537+
if (found_unit == false)
538+
return;
539+
481540
unit->setPosition(*startpos);
482541

483542
// stats

src/Battlescape/BattlescapeGame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ class BattlescapeGame
175175
std::string getCoopWeaponHand();
176176
void movePlayerTarget(std::string obj);
177177
void turnPlayerTarget(std::string str_obj);
178+
void turnPlayerTargetAfter(std::string str_obj);
178179
void psi_attack(std::string str_obj);
179180
void melee_attack(std::string str_obj);
180181
bool getHost();

0 commit comments

Comments
 (0)