mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
commit
cf47fbb729
@ -634,6 +634,8 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
|
||||
pos.y = y;
|
||||
frameTime = 0.0;
|
||||
|
||||
auto lastTimePoint = boost::chrono::steady_clock::now();
|
||||
|
||||
while(nextFrame())
|
||||
{
|
||||
if(stopOnKey)
|
||||
@ -654,10 +656,17 @@ bool CVideoPlayer::playVideo(int x, int y, bool stopOnKey)
|
||||
#else
|
||||
auto packet_duration = frame->duration;
|
||||
#endif
|
||||
double frameDurationSec = packet_duration * av_q2d(format->streams[stream]->time_base);
|
||||
uint32_t timeToSleepMillisec = 1000 * (frameDurationSec);
|
||||
// Framerate delay
|
||||
double targetFrameTimeSeconds = packet_duration * av_q2d(format->streams[stream]->time_base);
|
||||
auto targetFrameTime = boost::chrono::milliseconds(static_cast<int>(1000 * (targetFrameTimeSeconds)));
|
||||
|
||||
boost::this_thread::sleep_for(boost::chrono::milliseconds(timeToSleepMillisec));
|
||||
auto timePointAfterPresent = boost::chrono::steady_clock::now();
|
||||
auto timeSpentBusy = boost::chrono::duration_cast<boost::chrono::milliseconds>(timePointAfterPresent - lastTimePoint);
|
||||
|
||||
if (targetFrameTime > timeSpentBusy)
|
||||
boost::this_thread::sleep_for(targetFrameTime - timeSpentBusy);
|
||||
|
||||
lastTimePoint = boost::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1730,7 +1730,7 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "CREATURE_GROWTH",
|
||||
"subtype" : "creatureLevel1",
|
||||
"subtype" : "creatureLevel2",
|
||||
"val" : 5,
|
||||
"propagator": "VISITED_TOWN_AND_VISITOR"
|
||||
}
|
||||
@ -1743,7 +1743,7 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "CREATURE_GROWTH",
|
||||
"subtype" : "creatureLevel2",
|
||||
"subtype" : "creatureLevel3",
|
||||
"val" : 4,
|
||||
"propagator": "VISITED_TOWN_AND_VISITOR"
|
||||
}
|
||||
@ -1756,7 +1756,7 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "CREATURE_GROWTH",
|
||||
"subtype" : "creatureLevel3",
|
||||
"subtype" : "creatureLevel4",
|
||||
"val" : 3,
|
||||
"propagator": "VISITED_TOWN_AND_VISITOR"
|
||||
}
|
||||
@ -1769,7 +1769,7 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "CREATURE_GROWTH",
|
||||
"subtype" : "creatureLevel4",
|
||||
"subtype" : "creatureLevel5",
|
||||
"val" : 2,
|
||||
"propagator": "VISITED_TOWN_AND_VISITOR"
|
||||
}
|
||||
@ -1782,7 +1782,7 @@
|
||||
"bonuses" : [
|
||||
{
|
||||
"type" : "CREATURE_GROWTH",
|
||||
"subtype" : "creatureLevel5",
|
||||
"subtype" : "creatureLevel6",
|
||||
"val" : 1,
|
||||
"propagator": "VISITED_TOWN_AND_VISITOR"
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ Increased effect of spell affecting creature, ie. Aenain makes Disrupting Ray de
|
||||
"subtype" : "spell.disruptingRay",
|
||||
"type" : "SPECIAL_ADD_VALUE_ENCHANT"
|
||||
}
|
||||
``````
|
||||
```
|
||||
|
||||
- subtype: affected spell identifier
|
||||
- additionalInfo: value to add
|
||||
|
@ -21,6 +21,7 @@ BattleFieldInfo * BattleFieldHandler::loadFromJson(const std::string & scope, co
|
||||
|
||||
auto * info = new BattleFieldInfo(BattleField(index), identifier);
|
||||
|
||||
info->modScope = scope;
|
||||
info->graphics = ImagePath::fromJson(json["graphics"]);
|
||||
info->icon = json["icon"].String();
|
||||
info->name = json["name"].String();
|
||||
@ -66,7 +67,7 @@ int32_t BattleFieldInfo::getIconIndex() const
|
||||
|
||||
std::string BattleFieldInfo::getJsonKey() const
|
||||
{
|
||||
return identifier;
|
||||
return modScope + ':' + identifier;
|
||||
}
|
||||
|
||||
std::string BattleFieldInfo::getNameTextID() const
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
bool isSpecial;
|
||||
ImagePath graphics;
|
||||
std::string name;
|
||||
std::string modScope;
|
||||
std::string identifier;
|
||||
std::string icon;
|
||||
si32 iconIndex;
|
||||
|
@ -612,10 +612,20 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
|
||||
cre->addBonus(node["attack"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::ATTACK));
|
||||
cre->addBonus(node["defense"].Integer(), BonusType::PRIMARY_SKILL, BonusSubtypeID(PrimarySkill::DEFENSE));
|
||||
|
||||
cre->addBonus(node["damage"]["min"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
|
||||
cre->addBonus(node["damage"]["max"].Integer(), BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
|
||||
int minDamage = node["damage"]["min"].Integer();
|
||||
int maxDamage = node["damage"]["max"].Integer();
|
||||
|
||||
assert(node["damage"]["min"].Integer() <= node["damage"]["max"].Integer());
|
||||
if (minDamage <= maxDamage)
|
||||
{
|
||||
cre->addBonus(minDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
|
||||
cre->addBonus(maxDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->error("Mod %s: creature %s has minimal damage (%d) greater than maximal damage (%d)!", scope, identifier, minDamage, maxDamage);
|
||||
cre->addBonus(maxDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMin);
|
||||
cre->addBonus(minDamage, BonusType::CREATURE_DAMAGE, BonusCustomSubtype::creatureDamageMax);
|
||||
}
|
||||
|
||||
if(!node["shots"].isNull())
|
||||
cre->addBonus(node["shots"].Integer(), BonusType::SHOTS);
|
||||
|
@ -320,7 +320,7 @@ void CGDwelling::newTurn(CRandomGenerator & rand) const
|
||||
creaturesAccumulate = VLC->settings()->getBoolean(EGameSettings::DWELLINGS_ACCUMULATE_WHEN_NEUTRAL);
|
||||
|
||||
const CCreature * cre =creatures[i].second[0].toCreature();
|
||||
TQuantity amount = cre->getGrowth() * (1 + cre->valOfBonuses(BonusType::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(BonusType::CREATURE_GROWTH);
|
||||
TQuantity amount = cre->getGrowth() * (1 + cre->valOfBonuses(BonusType::CREATURE_GROWTH_PERCENT)/100) + cre->valOfBonuses(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(cre->getLevel()));
|
||||
if (creaturesAccumulate && ID != Obj::REFUGEE_CAMP) //camp should not try to accumulate different kinds of creatures
|
||||
sac.creatures[i].first += amount;
|
||||
else
|
||||
|
@ -164,7 +164,8 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
|
||||
}
|
||||
|
||||
//other *-of-legion-like bonuses (%d to growth cumulative with grail)
|
||||
TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(level)));
|
||||
// Note: bonus uses 1-based levels (Pikeman is level 1), town list uses 0-based (Pikeman in 0-th creatures entry)
|
||||
TConstBonusListPtr bonuses = getBonuses(Selector::typeSubtype(BonusType::CREATURE_GROWTH, BonusCustomSubtype::creatureLevel(level+1)));
|
||||
for(const auto & b : *bonuses)
|
||||
ret.entries.emplace_back(b->val, b->Description());
|
||||
|
||||
|
@ -2223,17 +2223,10 @@ CGObjectInstance * CMapLoaderH3M::readTown(const int3 & position, std::shared_pt
|
||||
}
|
||||
|
||||
{
|
||||
std::set<SpellID> spellsMask;
|
||||
std::set<SpellID> spellsMask = VLC->spellh->getDefaultAllowed(); // by default - include spells from mods
|
||||
|
||||
reader->readBitmaskSpells(spellsMask, true);
|
||||
std::copy(spellsMask.begin(), spellsMask.end(), std::back_inserter(object->possibleSpells));
|
||||
|
||||
auto defaultAllowed = VLC->spellh->getDefaultAllowed();
|
||||
|
||||
//add all spells from mods
|
||||
for(int i = features.spellsCount; i < defaultAllowed.size(); ++i)
|
||||
if(defaultAllowed.count(i))
|
||||
object->possibleSpells.emplace_back(i);
|
||||
}
|
||||
|
||||
if(features.levelHOTA1)
|
||||
|
@ -71,7 +71,8 @@ SilentCaster::SilentCaster(PlayerColor owner_, const Caster * hero_):
|
||||
|
||||
void SilentCaster::getCasterName(MetaString & text) const
|
||||
{
|
||||
logGlobal->error("Unexpected call to SilentCaster::getCasterName");
|
||||
// NOTE: can be triggered (for example) if creature steps into Tower mines/moat while hero has Recanter's Cloak
|
||||
logGlobal->debug("Unexpected call to SilentCaster::getCasterName");
|
||||
}
|
||||
|
||||
void SilentCaster::getCastDescription(const Spell * spell, const std::vector<const battle::Unit *> & attacked, MetaString & text) const
|
||||
|
@ -3292,7 +3292,11 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
|
||||
|
||||
for (auto & i : ev.buildings)
|
||||
{
|
||||
if (!town->hasBuilt(i))
|
||||
// Only perform action if:
|
||||
// 1. Building exists in town (don't attempt to build Lvl 5 guild in Fortress
|
||||
// 2. Building was not built yet
|
||||
// othervice, silently ignore / skip it
|
||||
if (town->town->buildings.count(i) && !town->hasBuilt(i))
|
||||
{
|
||||
buildStructure(town->id, i, true);
|
||||
iw.components.emplace_back(ComponentType::BUILDING, BuildingTypeUniqueID(town->getFaction(), i));
|
||||
|
@ -1301,6 +1301,7 @@ void BattleActionProcessor::handleAfterAttackCasting(const CBattleInfoCallback &
|
||||
// send empty event to client
|
||||
// temporary(?) workaround to force animations to trigger
|
||||
StacksInjured fakeEvent;
|
||||
fakeEvent.battleID = battle.getBattle()->getBattleID();
|
||||
gameHandler->sendAndApply(&fakeEvent);
|
||||
}
|
||||
|
||||
|
@ -181,6 +181,7 @@ void BattleFlowProcessor::trySummonGuardians(const CBattleInfoCallback & battle,
|
||||
// send empty event to client
|
||||
// temporary(?) workaround to force animations to trigger
|
||||
StacksInjured fakeEvent;
|
||||
fakeEvent.battleID = battle.getBattle()->getBattleID();
|
||||
gameHandler->sendAndApply(&fakeEvent);
|
||||
}
|
||||
|
||||
@ -676,8 +677,7 @@ void BattleFlowProcessor::stackTurnTrigger(const CBattleInfoCallback & battle, c
|
||||
}
|
||||
if(st->hasBonusOfType(BonusType::MANA_DRAIN) && !st->drainedMana)
|
||||
{
|
||||
const PlayerColor opponent = battle.otherPlayer(battle.battleGetOwner(st));
|
||||
const CGHeroInstance * opponentHero = battle.battleGetFightingHero(opponent);
|
||||
const CGHeroInstance * opponentHero = battle.battleGetFightingHero(battle.otherSide(st->unitSide()));
|
||||
if(opponentHero)
|
||||
{
|
||||
ui32 manaDrained = st->valOfBonuses(BonusType::MANA_DRAIN);
|
||||
|
@ -498,10 +498,10 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
|
||||
BattleResultAccepted raccepted;
|
||||
raccepted.battleID = battle.getBattle()->getBattleID();
|
||||
raccepted.heroResult[0].army = const_cast<CArmedInstance*>(battle.battleGetArmyObject(0));
|
||||
raccepted.heroResult[1].army = const_cast<CArmedInstance*>(battle.battleGetArmyObject(1));
|
||||
raccepted.heroResult[0].hero = const_cast<CGHeroInstance*>(battle.battleGetFightingHero(0));
|
||||
raccepted.heroResult[1].hero = const_cast<CGHeroInstance*>(battle.battleGetFightingHero(1));
|
||||
raccepted.heroResult[0].army = const_cast<CArmedInstance*>(battle.battleGetArmyObject(BattleSide::ATTACKER));
|
||||
raccepted.heroResult[1].army = const_cast<CArmedInstance*>(battle.battleGetArmyObject(BattleSide::DEFENDER));
|
||||
raccepted.heroResult[0].hero = const_cast<CGHeroInstance*>(battle.battleGetFightingHero(BattleSide::ATTACKER));
|
||||
raccepted.heroResult[1].hero = const_cast<CGHeroInstance*>(battle.battleGetFightingHero(BattleSide::DEFENDER));
|
||||
raccepted.heroResult[0].exp = battleResult->exp[0];
|
||||
raccepted.heroResult[1].exp = battleResult->exp[1];
|
||||
raccepted.winnerSide = finishingBattle->winnerSide;
|
||||
|
Loading…
Reference in New Issue
Block a user