mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
- Implemented guard generation formula following this post http://forum.vcmi.eu/viewtopic.php?p=12426&sid=09f5fac8992dc880eb6a720615787ca0#12426
- Some primitive way to randomize treasures
This commit is contained in:
parent
6221f4ac2c
commit
62e9f13b08
@ -1709,7 +1709,7 @@ CRandomMapTab::CRandomMapTab()
|
|||||||
addButtonsWithRandToGroup(monsterStrengthGroup, monsterStrengthBtns, 0, 2, WIDE_BTN_WIDTH, 248, 251);
|
addButtonsWithRandToGroup(monsterStrengthGroup, monsterStrengthBtns, 0, 2, WIDE_BTN_WIDTH, 248, 251);
|
||||||
monsterStrengthGroup->onChange = [&](int btnId)
|
monsterStrengthGroup->onChange = [&](int btnId)
|
||||||
{
|
{
|
||||||
mapGenOptions.setMonsterStrength(static_cast<EMonsterStrength::EMonsterStrength>(btnId));
|
mapGenOptions.setMonsterStrength(static_cast<EMonsterStrength::EMonsterStrength>(btnId + EMonsterStrength::GLOBAL_WEAK)); //value 2 to 4
|
||||||
};
|
};
|
||||||
|
|
||||||
// Show random maps btn
|
// Show random maps btn
|
||||||
|
@ -70,12 +70,12 @@
|
|||||||
},
|
},
|
||||||
"connections" :
|
"connections" :
|
||||||
[
|
[
|
||||||
{ "a" : "1", "b" : "3", "guard" : 2000 },
|
{ "a" : "1", "b" : "3", "guard" : 3000 },
|
||||||
{ "a" : "1", "b" : "5", "guard" : 8000 },
|
{ "a" : "1", "b" : "5", "guard" : 9000 },
|
||||||
{ "a" : "2", "b" : "4", "guard" : 2000 },
|
{ "a" : "2", "b" : "4", "guard" : 3000 },
|
||||||
{ "a" : "2", "b" : "5", "guard" : 8000 },
|
{ "a" : "2", "b" : "5", "guard" : 9000 },
|
||||||
{ "a" : "3", "b" : "5", "guard" : 4000 },
|
{ "a" : "3", "b" : "5", "guard" : 6000 },
|
||||||
{ "a" : "4", "b" : "5", "guard" : 4000 }
|
{ "a" : "4", "b" : "5", "guard" : 6000 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"Golden Ring" :
|
"Golden Ring" :
|
||||||
@ -111,12 +111,12 @@
|
|||||||
},
|
},
|
||||||
"connections" :
|
"connections" :
|
||||||
[
|
[
|
||||||
{ "a" : "1", "b" : "4", "guard" : 2000 },
|
{ "a" : "1", "b" : "4", "guard" : 2500 },
|
||||||
{ "a" : "1", "b" : "5", "guard" : 2000 },
|
{ "a" : "1", "b" : "5", "guard" : 2500 },
|
||||||
{ "a" : "2", "b" : "6", "guard" : 2000 },
|
{ "a" : "2", "b" : "6", "guard" : 2500 },
|
||||||
{ "a" : "2", "b" : "7", "guard" : 2000 },
|
{ "a" : "2", "b" : "7", "guard" : 2500 },
|
||||||
{ "a" : "3", "b" : "8", "guard" : 2000 },
|
{ "a" : "3", "b" : "8", "guard" : 2500 },
|
||||||
{ "a" : "3", "b" : "9", "guard" : 2000 },
|
{ "a" : "3", "b" : "9", "guard" : 2500 },
|
||||||
{ "a" : "4", "b" : "10", "guard" : 20000 },
|
{ "a" : "4", "b" : "10", "guard" : 20000 },
|
||||||
{ "a" : "5", "b" : "12", "guard" : 20000 },
|
{ "a" : "5", "b" : "12", "guard" : 20000 },
|
||||||
{ "a" : "6", "b" : "10", "guard" : 20000 },
|
{ "a" : "6", "b" : "10", "guard" : 20000 },
|
||||||
|
@ -216,11 +216,11 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
|
|||||||
|
|
||||||
if(waterContent == EWaterContent::RANDOM)
|
if(waterContent == EWaterContent::RANDOM)
|
||||||
{
|
{
|
||||||
waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(EWaterContent::LAST_ITEM));
|
waterContent = static_cast<EWaterContent::EWaterContent>(rand.nextInt(EWaterContent::NONE, EWaterContent::ISLANDS));
|
||||||
}
|
}
|
||||||
if(monsterStrength == EMonsterStrength::RANDOM)
|
if(monsterStrength == EMonsterStrength::RANDOM)
|
||||||
{
|
{
|
||||||
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::LAST_ITEM));
|
monsterStrength = static_cast<EMonsterStrength::EMonsterStrength>(rand.nextInt(EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG));
|
||||||
}
|
}
|
||||||
|
|
||||||
//rectangular maps are the future of gaming
|
//rectangular maps are the future of gaming
|
||||||
|
@ -23,8 +23,7 @@ namespace EWaterContent
|
|||||||
RANDOM = -1,
|
RANDOM = -1,
|
||||||
NONE,
|
NONE,
|
||||||
NORMAL,
|
NORMAL,
|
||||||
ISLANDS,
|
ISLANDS
|
||||||
LAST_ITEM = ISLANDS
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,11 +31,13 @@ namespace EMonsterStrength
|
|||||||
{
|
{
|
||||||
enum EMonsterStrength
|
enum EMonsterStrength
|
||||||
{
|
{
|
||||||
RANDOM = -1,
|
RANDOM = -2,
|
||||||
WEAK,
|
ZONE_WEAK = -1,
|
||||||
NORMAL,
|
ZONE_NORMAL = 0,
|
||||||
STRONG,
|
ZONE_STRONG = 1,
|
||||||
LAST_ITEM = STRONG
|
GLOBAL_WEAK = 2,
|
||||||
|
GLOBAL_NORMAL = 3,
|
||||||
|
GLOBAL_STRONG = 4
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +258,7 @@ void CMapGenerator::createConnections()
|
|||||||
});
|
});
|
||||||
if (guardPos.valid())
|
if (guardPos.valid())
|
||||||
{
|
{
|
||||||
|
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
|
||||||
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
|
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
|
||||||
//zones can make paths only in their own area
|
//zones can make paths only in their own area
|
||||||
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center
|
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId()); //make connection towards our zone center
|
||||||
|
@ -403,16 +403,38 @@ void CRmgTemplateZone::addRequiredObject(CGObjectInstance * obj, si32 strength)
|
|||||||
|
|
||||||
void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
|
void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
|
||||||
{
|
{
|
||||||
|
//precalculate actual (randomized) monster strength based on this post
|
||||||
|
//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
|
||||||
|
|
||||||
|
int zoneMonsterStrength = 0; //TODO: range -1..1 based on template settings
|
||||||
|
int mapMonsterStrength = gen->mapGenOptions->getMonsterStrength();
|
||||||
|
int monsterStrength = zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
|
||||||
|
static const int value1[] = {2500, 1500, 1000, 500, 0};
|
||||||
|
static const int value2[] = {7500, 7500, 7500, 5000, 5000};
|
||||||
|
static const float multiplier1[] = {0.5, 0.75, 1.0, 1.5, 1.5};
|
||||||
|
static const float multiplier2[] = {0.5, 0.75, 1.0, 1.0, 1.5};
|
||||||
|
|
||||||
|
int strength1 = std::max(0.f, (strength - value1[monsterStrength]) * multiplier1[monsterStrength]);
|
||||||
|
int strength2 = std::max(0.f, (strength - value2[monsterStrength]) * multiplier2[monsterStrength]);
|
||||||
|
|
||||||
|
strength = strength1 + strength2;
|
||||||
|
if (strength < 2000)
|
||||||
|
return; //no guard at all
|
||||||
|
|
||||||
CreatureID creId = CreatureID::NONE;
|
CreatureID creId = CreatureID::NONE;
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
creId = VLC->creh->pickRandomMonster(gen->rand);
|
creId = VLC->creh->pickRandomMonster(gen->rand);
|
||||||
auto cre = VLC->creh->creatures[creId];
|
auto cre = VLC->creh->creatures[creId];
|
||||||
amount = std::ceil((float)strength / cre->fightValue);
|
if ((cre->AIValue * (cre->ammMin + cre->ammMax) / 2 < strength) && (strength < cre->AIValue * 100)) //at leats one full monster. size between minimum size of given stack and 100
|
||||||
if (strength >= cre->fightValue && amount >= cre->ammMin && amount <= 100) //at leats one full monster. size between minimum size of given stack and 100
|
{
|
||||||
|
amount = strength / cre->AIValue;
|
||||||
|
if (amount >= 4)
|
||||||
|
amount *= gen->rand.nextDouble(0.75, 1.25);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto guard = new CGCreature();
|
auto guard = new CGCreature();
|
||||||
guard->ID = Obj::MONSTER;
|
guard->ID = Obj::MONSTER;
|
||||||
@ -424,6 +446,119 @@ void CRmgTemplateZone::addMonster(CMapGenerator* gen, int3 &pos, si32 strength)
|
|||||||
placeObject(gen, guard, pos);
|
placeObject(gen, guard, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CRmgTemplateZone::createTreasurePile (CMapGenerator* gen, int3 &pos)
|
||||||
|
{
|
||||||
|
//TODO: read treasure values from template
|
||||||
|
const int maxValue = 5000;
|
||||||
|
const int minValue = 1500;
|
||||||
|
|
||||||
|
static const Res::ERes woodOre[] = {Res::ERes::WOOD, Res::ERes::ORE};
|
||||||
|
static const Res::ERes preciousRes[] = {Res::ERes::CRYSTAL, Res::ERes::GEMS, Res::ERes::MERCURY, Res::ERes::SULFUR};
|
||||||
|
static auto res_gen = gen->rand.getIntRange(Res::ERes::WOOD, Res::ERes::GOLD);
|
||||||
|
|
||||||
|
int currentValue = 0;
|
||||||
|
CGObjectInstance * object = nullptr;
|
||||||
|
while (currentValue < minValue)
|
||||||
|
{
|
||||||
|
int remaining = maxValue - currentValue;
|
||||||
|
int nextValue = gen->rand.nextInt (0.25f * remaining, remaining);
|
||||||
|
|
||||||
|
if (nextValue >= 20000)
|
||||||
|
{
|
||||||
|
auto obj = new CGArtifact();
|
||||||
|
obj->ID = Obj::RANDOM_RELIC_ART;
|
||||||
|
obj->subID = 0;
|
||||||
|
auto a = new CArtifactInstance(); //TODO: probably some refactoring could help here
|
||||||
|
gen->map->addNewArtifactInstance(a);
|
||||||
|
obj->storedArtifact = a;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 20000;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 10000)
|
||||||
|
{
|
||||||
|
auto obj = new CGArtifact();
|
||||||
|
obj->ID = Obj::RANDOM_MAJOR_ART;
|
||||||
|
obj->subID = 0;
|
||||||
|
auto a = new CArtifactInstance();
|
||||||
|
gen->map->addNewArtifactInstance(a);
|
||||||
|
obj->storedArtifact = a;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 10000;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 5000)
|
||||||
|
{
|
||||||
|
auto obj = new CGArtifact();
|
||||||
|
obj->ID = Obj::RANDOM_MINOR_ART;
|
||||||
|
obj->subID = 0;
|
||||||
|
auto a = new CArtifactInstance();
|
||||||
|
gen->map->addNewArtifactInstance(a);
|
||||||
|
obj->storedArtifact = a;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 5000;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 2000)
|
||||||
|
{
|
||||||
|
auto obj = new CGArtifact();
|
||||||
|
obj->ID = Obj::RANDOM_TREASURE_ART;
|
||||||
|
obj->subID = 0;
|
||||||
|
auto a = new CArtifactInstance();
|
||||||
|
gen->map->addNewArtifactInstance(a);
|
||||||
|
obj->storedArtifact = a;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 2000;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 1500)
|
||||||
|
{
|
||||||
|
auto obj = new CGPickable();
|
||||||
|
obj->ID = Obj::TREASURE_CHEST;
|
||||||
|
obj->subID = 0;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 1500;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 1400)
|
||||||
|
{
|
||||||
|
auto obj = new CGResource();
|
||||||
|
auto restype = static_cast<Res::ERes>(preciousRes[gen->rand.nextInt (0,3)]); //TODO: how about dedicated function to pick random element of array?
|
||||||
|
obj->ID = Obj::RESOURCE;
|
||||||
|
obj->subID = static_cast<si32>(restype);
|
||||||
|
obj->amount = 0;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 1400;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 1000)
|
||||||
|
{
|
||||||
|
auto obj = new CGResource();
|
||||||
|
auto restype = static_cast<Res::ERes>(woodOre[gen->rand.nextInt (0,1)]);
|
||||||
|
obj->ID = Obj::RESOURCE;
|
||||||
|
obj->subID = static_cast<si32>(restype);
|
||||||
|
obj->amount = 0;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 1000;
|
||||||
|
}
|
||||||
|
else if (nextValue >= 750)
|
||||||
|
{
|
||||||
|
auto obj = new CGResource();
|
||||||
|
obj->ID = Obj::RESOURCE;
|
||||||
|
obj->subID = static_cast<si32>(Res::ERes::GOLD);
|
||||||
|
obj->amount = 0;
|
||||||
|
object = obj;
|
||||||
|
currentValue += 750;
|
||||||
|
}
|
||||||
|
else //no possible treasure left (should not happen)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//TODO: generate actual zone and not just all objects on a pile
|
||||||
|
placeObject(gen, object, pos);
|
||||||
|
}
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
guardObject (gen, object, currentValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else //we did not place eveyrthing successfully
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
||||||
{
|
{
|
||||||
int townId = 0;
|
int townId = 0;
|
||||||
@ -515,15 +650,14 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
|||||||
guardObject (gen, obj.first, obj.second);
|
guardObject (gen, obj.first, obj.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<CGObjectInstance*> guarded_objects;
|
|
||||||
static auto res_gen = gen->rand.getIntRange(Res::ERes::WOOD, Res::ERes::GOLD);
|
|
||||||
const double res_mindist = 5;
|
const double res_mindist = 5;
|
||||||
do {
|
|
||||||
|
//TODO: just placeholder to chekc for possible locations
|
||||||
auto obj = new CGResource();
|
auto obj = new CGResource();
|
||||||
auto restype = static_cast<Res::ERes>(res_gen());
|
|
||||||
obj->ID = Obj::RESOURCE;
|
obj->ID = Obj::RESOURCE;
|
||||||
obj->subID = static_cast<si32>(restype);
|
obj->subID = static_cast<si32>(Res::ERes::GOLD);
|
||||||
obj->amount = 0;
|
obj->amount = 0;
|
||||||
|
do {
|
||||||
|
|
||||||
int3 pos;
|
int3 pos;
|
||||||
if ( ! findPlaceForObject(gen, obj, res_mindist, pos))
|
if ( ! findPlaceForObject(gen, obj, res_mindist, pos))
|
||||||
@ -531,22 +665,10 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
|
|||||||
delete obj;
|
delete obj;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
placeObject(gen, obj, pos);
|
createTreasurePile (gen, pos);
|
||||||
|
|
||||||
if ((restype != Res::ERes::WOOD) && (restype != Res::ERes::ORE))
|
|
||||||
{
|
|
||||||
guarded_objects.push_back(obj);
|
|
||||||
}
|
|
||||||
} while(true);
|
} while(true);
|
||||||
|
|
||||||
for(const auto &obj : guarded_objects)
|
|
||||||
{
|
|
||||||
if ( ! guardObject(gen, obj, 1000))
|
|
||||||
{
|
|
||||||
//TODO, DEL obj from map
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto sel = gen->editManager->getTerrainSelection();
|
auto sel = gen->editManager->getTerrainSelection();
|
||||||
sel.clearSelection();
|
sel.clearSelection();
|
||||||
for (auto tile : tileinfo)
|
for (auto tile : tileinfo)
|
||||||
|
@ -114,6 +114,7 @@ public:
|
|||||||
|
|
||||||
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
|
||||||
void addMonster(CMapGenerator* gen, int3 &pos, si32 strength);
|
void addMonster(CMapGenerator* gen, int3 &pos, si32 strength);
|
||||||
|
bool createTreasurePile (CMapGenerator* gen, int3 &pos);
|
||||||
bool fill(CMapGenerator* gen);
|
bool fill(CMapGenerator* gen);
|
||||||
void createBorder(CMapGenerator* gen);
|
void createBorder(CMapGenerator* gen);
|
||||||
bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone);
|
bool crunchPath (CMapGenerator* gen, const int3 &src, const int3 &dst, TRmgTemplateZoneId zone);
|
||||||
|
Loading…
Reference in New Issue
Block a user