mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #1486 from IvanSavenko/configurable_rewardables
Well, it works for my brand new objects with arbitrary bonus, so likely will work with everything else.
This commit is contained in:
		| @@ -314,8 +314,9 @@ bool isWeeklyRevisitable(const CGObjectInstance * obj) | ||||
| 		return false; | ||||
|  | ||||
| 	//TODO: allow polling of remaining creatures in dwelling | ||||
| 	if(dynamic_cast<const CGVisitableOPW *>(obj)) // ensures future compatibility, unlike IDs | ||||
| 		return true; | ||||
| 	if(const auto * rewardable = dynamic_cast<const CRewardableObject *>(obj)) | ||||
| 		return rewardable->getResetDuration() == 7; | ||||
|  | ||||
| 	if(dynamic_cast<const CGDwelling *>(obj)) | ||||
| 		return true; | ||||
| 	if(dynamic_cast<const CBank *>(obj)) //banks tend to respawn often in mods | ||||
|   | ||||
| @@ -70,12 +70,15 @@ void AIMemory::markObjectVisited(const CGObjectInstance * obj) | ||||
| 		return; | ||||
| 	 | ||||
| 	// TODO: maybe this logic belongs to CaptureObjects::shouldVisit | ||||
| 	if(dynamic_cast<const CGVisitableOPH *>(obj)) //we may want to visit it with another hero | ||||
| 		return; | ||||
| 	 | ||||
| 	if(dynamic_cast<const CGBonusingObject *>(obj)) //or another time | ||||
| 		return; | ||||
| 	 | ||||
| 	if(const auto * rewardable = dynamic_cast<const CRewardableObject *>(obj)) | ||||
| 	{ | ||||
| 		if (rewardable->getVisitMode() == CRewardableObject::VISIT_HERO) //we may want to visit it with another hero | ||||
| 			return; | ||||
|  | ||||
| 		if (rewardable->getVisitMode() == CRewardableObject::VISIT_BONUS) //or another time | ||||
| 			return; | ||||
| 	} | ||||
|  | ||||
| 	if(obj->ID == Obj::MONSTER) | ||||
| 		return; | ||||
|  | ||||
|   | ||||
| @@ -29,12 +29,6 @@ | ||||
|  | ||||
| extern FuzzyHelper * fh; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| class CGVisitableOPW; | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_END | ||||
|  | ||||
| const double SAFE_ATTACK_CONSTANT = 1.5; | ||||
|  | ||||
| //one thread may be turn of AI and another will be handling a side effect for AI2 | ||||
| @@ -1606,12 +1600,19 @@ void VCAI::markObjectVisited(const CGObjectInstance * obj) | ||||
| { | ||||
| 	if(!obj) | ||||
| 		return; | ||||
| 	if(dynamic_cast<const CGVisitableOPH *>(obj)) //we may want to visit it with another hero | ||||
| 		return; | ||||
| 	if(dynamic_cast<const CGBonusingObject *>(obj)) //or another time | ||||
| 		return; | ||||
|  | ||||
| 	if(const auto * rewardable = dynamic_cast<const CRewardableObject *>(obj)) //we may want to visit it with another hero | ||||
| 	{ | ||||
| 		if (rewardable->getVisitMode() == CRewardableObject::VISIT_HERO) //we may want to visit it with another hero | ||||
| 			return; | ||||
|  | ||||
| 		if (rewardable->getVisitMode() == CRewardableObject::VISIT_BONUS) //or another time | ||||
| 			return; | ||||
| 	} | ||||
|  | ||||
| 	if(obj->ID == Obj::MONSTER) | ||||
| 		return; | ||||
|  | ||||
| 	alreadyVisited.insert(obj); | ||||
| } | ||||
|  | ||||
| @@ -2742,8 +2743,9 @@ bool AIStatus::channelProbing() | ||||
| bool isWeeklyRevisitable(const CGObjectInstance * obj) | ||||
| { | ||||
| 	//TODO: allow polling of remaining creatures in dwelling | ||||
| 	if(dynamic_cast<const CGVisitableOPW *>(obj)) // ensures future compatibility, unlike IDs | ||||
| 		return true; | ||||
| 	if(const auto * rewardable = dynamic_cast<const CRewardableObject *>(obj)) | ||||
| 		return rewardable->getResetDuration() == 7; | ||||
|  | ||||
| 	if(dynamic_cast<const CGDwelling *>(obj)) | ||||
| 		return true; | ||||
| 	if(dynamic_cast<const CBank *>(obj)) //banks tend to respawn often in mods | ||||
|   | ||||
| @@ -51,7 +51,11 @@ | ||||
| 		"config/objects/moddables.json", | ||||
| 		"config/objects/creatureBanks.json", | ||||
| 		"config/objects/dwellings.json", | ||||
| 		"config/objects/rewardable.json" | ||||
| 		"config/objects/rewardableOncePerWeek.json", | ||||
| 		"config/objects/rewardablePickable.json", | ||||
| 		"config/objects/rewardableOnceVisitable.json", | ||||
| 		"config/objects/rewardableOncePerHero.json", | ||||
| 		"config/objects/rewardableBonusing.json" | ||||
| 	], | ||||
|  | ||||
| 	"artifacts" : | ||||
|   | ||||
| @@ -597,28 +597,6 @@ | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"magicWell" : { | ||||
| 		"index" :49, | ||||
| 		"handler" : "magicWell", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 250, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit" : 1, | ||||
| 					"value"		: 250, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			}, | ||||
| 			"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	/// Random objects | ||||
| 	"randomTown"					: { "index" :77,  "handler": "randomTown", "types" : { "object" : { "index" : 0} }  }, | ||||
| 	"randomHero" : { | ||||
|   | ||||
| @@ -1,716 +0,0 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" | ||||
| 	/// Most or even all of their configuration located in this file | ||||
| 	"magicSpring" : {//magic source | ||||
| 		"index" : 48, | ||||
| 		"handler": "magicSpring", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFOUN"], | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500//, | ||||
| 				//"rmg" : { | ||||
| 				//	"zoneLimit"	: 1, | ||||
| 				//	"value"		: 500, | ||||
| 				//	"rarity"	: 50 | ||||
| 				//} | ||||
| 				//banned due to problems with 2 viistable offsets | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	"mysticalGarden" : { | ||||
| 		"index" : 55, | ||||
| 		"handler": "oncePerWeek", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPLEPR"], | ||||
| 				"visit" : ["EXPERNCE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"windmill" :{ | ||||
| 		"index" : 112, | ||||
| 		"handler": "oncePerWeek", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPWIND"], | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 80 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"waterWheel" : { | ||||
| 		"index" : 109, | ||||
| 		"handler": "oncePerWeek", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMILL"], | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 750, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 750, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	 | ||||
| 	"leanTo" :{ | ||||
| 		"index" : 39, | ||||
| 		"handler": "onceVisitable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"corpse" :{ | ||||
| 		"index" : 22, | ||||
| 		"handler": "onceVisitable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MYSTERY"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"wagon" :{ | ||||
| 		"index" : 105, | ||||
| 		"handler": "onceVisitable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"warriorTomb" : { | ||||
| 		"index" : 108, | ||||
| 		"handler": "onceVisitable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GRAVEYARD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 6000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 6000, | ||||
| 					"rarity"	: 20 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	"campfire" :{ | ||||
| 		"index" : 12, | ||||
| 		"handler": "pickable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPCAMP"], | ||||
| 				"visit" : ["EXPERNCE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 2000, | ||||
| 					"rarity"	: 500 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"flotsam" :{ | ||||
| 		"index" : 29, | ||||
| 		"handler": "pickable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 2000, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"seaChest" :{ | ||||
| 		"index" : 82, | ||||
| 		"handler": "pickable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["CHEST"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 500 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"shipwreckSurvivor" : { | ||||
| 		"index" : 86, | ||||
| 		"handler": "pickable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["TREASURE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"treasureChest" : { | ||||
| 		"index" : 101, | ||||
| 		"handler": "pickable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["CHEST"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 1000 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	"arena" : { | ||||
| 		"index" : 4, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPAREN"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 3000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 3000, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"marlettoTower" : { | ||||
| 		"index" : 23, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSWAR"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"gardenOfRevelation" : { | ||||
| 		"index" : 32, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPGARD"], | ||||
| 				"visit" : ["GETPROTECTION"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"libraryOfEnlightenment" : { | ||||
| 		"index" : 41, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 12000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 12000, | ||||
| 					"rarity"	: 20 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"mercenaryCamp" : { | ||||
| 		"index" : 51, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMERC"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"starAxis" :{ | ||||
| 		"index" : 61, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSTAR"], | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"treeOfKnowledge" : { | ||||
| 		"index" : 102, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2500, | ||||
| 				"rmg" : { | ||||
| 					"mapLimit"	: 100, | ||||
| 					"value"		: 2500, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"schoolOfMagic" : { | ||||
| 		"index" : 47, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMAGI"], | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1000, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"schoolOfWar" : { | ||||
| 		"index" : 107, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSWAR"], | ||||
| 				"visit" : ["MILITARY"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1000, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"learningStone" : { | ||||
| 		"index" : 100, | ||||
| 		"handler": "oncePerHero", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPLEAR"], | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : {  | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 200 | ||||
| 				}  | ||||
| 			}, | ||||
| 			"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI_Tests 2011 | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	"buoy" : { | ||||
| 		"index" : 11, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPBUOY"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"swanPond" : { | ||||
| 		"index" : 14, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"faerieRing" : { | ||||
| 		"index" : 28, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFAER"], | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"fountainOfFortune" : { | ||||
| 		"index" : 30, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFOUN"], | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"fountainOfYouth" : { | ||||
| 		"index" : 31, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFALL"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"idolOfFortune" : { | ||||
| 		"index" : 38, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			}, | ||||
| 			"object1" : {//WoG? | ||||
| 				"index" : 1 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"mermaids" : { | ||||
| 		"index" : 52, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 20 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"oasis" : { | ||||
| 		"index" : 56, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"stables" : { | ||||
| 		"index" : 94, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPHORS"], | ||||
| 				"visit" : ["STORE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 200, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 200, | ||||
| 					"rarity"	: 40 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"temple" : { | ||||
| 		"index" : 96, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSANC"], | ||||
| 				"visit" : ["TEMPLE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"rallyFlag" : { | ||||
| 		"index" : 64, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFLAG"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"wateringHole" : {//waters | ||||
| 		"index" : 110, | ||||
| 		"handler": "bonusingObject", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"object" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				} | ||||
| 			}  | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										457
									
								
								config/objects/rewardableBonusing.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										457
									
								
								config/objects/rewardableBonusing.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,457 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" and have their entire configuration in this config | ||||
|  | ||||
| 	"buoy" : { | ||||
| 		"index" : 11, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPBUOY"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"buoy" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"blockedVisitable" : true, | ||||
| 				"onVisitedMessage" : 22, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 21, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 94 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			}	 | ||||
| 		} | ||||
| 	}, | ||||
| 	"swanPond" : { | ||||
| 		"index" : 14, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"swanPond" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 30, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 29, | ||||
| 						"movePercentage" : 0, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 2, "duration" : "ONE_BATTLE", "description" : 67 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"faerieRing" : { | ||||
| 		"index" : 28, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFAER"], | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"faerieRing" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 50, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 49, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 71 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"fountainOfFortune" : { | ||||
| 		"index" : 30, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFOUN"], | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"fountainOfFortune" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 56, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"resetParameters" : { | ||||
| 					"period" : 7, | ||||
| 					"rewards" : true | ||||
| 				}, | ||||
|  | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 55, | ||||
| 						"appearChance" : { "min" : 0, "max" : 25 }, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : -1, "duration" : "ONE_BATTLE", "description" : 69 } ] // NOTE: strings has %s placeholder for morale value | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 55, | ||||
| 						"appearChance" : { "min" : 25, "max" : 50 }, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 69 } ] // NOTE: strings has %s placeholder for morale value | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 55, | ||||
| 						"appearChance" : { "min" : 50, "max" : 75 }, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 2, "duration" : "ONE_BATTLE", "description" : 69 } ] // NOTE: strings has %s placeholder for morale value | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 55, | ||||
| 						"appearChance" : { "min" : 75, "max" : 100 }, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 3, "duration" : "ONE_BATTLE", "description" : 69 } ] // NOTE: strings has %s placeholder for morale value | ||||
| 					}, | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"fountainOfYouth" : { | ||||
| 		"index" : 31, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFALL"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"fountainOfYouth" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 58, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 57, | ||||
| 						"movePoints" : 400, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 103 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"idolOfFortune" : { | ||||
| 		"index" : 38, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"idolOfFortune" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 63, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 62, | ||||
| 						"limiter" : {  | ||||
| 							"anyOf" : [ | ||||
| 								{ "dayOfWeek" : 1 }, | ||||
| 								{ "dayOfWeek" : 3 }, | ||||
| 								{ "dayOfWeek" : 5 } | ||||
| 							] | ||||
| 						}, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 68 } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 62, | ||||
| 						"limiter" : {  | ||||
| 							"anyOf" : [ | ||||
| 								{ "dayOfWeek" : 2 }, | ||||
| 								{ "dayOfWeek" : 4 }, | ||||
| 								{ "dayOfWeek" : 6 } | ||||
| 							] | ||||
| 						}, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 68 } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 62, | ||||
| 						"limiter" : { "dayOfWeek" : 7 }, | ||||
| 						"bonuses" : [  | ||||
| 							{ "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 68 }, | ||||
| 							{ "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 68 }   | ||||
| 						] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"mermaids" : { | ||||
| 		"index" : 52, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["LUCK"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"mermaids" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 20 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 82, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 83, | ||||
| 						"bonuses" : [ { "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 72 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"oasis" : { | ||||
| 		"index" : 56, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"oasis" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 95, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 94, | ||||
| 						"movePoints" : 800, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 95 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"stables" : { | ||||
| 		"index" : 94, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPHORS"], | ||||
| 				"visit" : ["STORE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"stables" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 200, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 200, | ||||
| 					"rarity"	: 40 | ||||
| 				}, | ||||
| 				 | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
|  | ||||
| 				"onVisited" : [ | ||||
| 					{ | ||||
| 						"message" : 139, | ||||
| 						"limiter" : { | ||||
| 							"creatures" : [ { "type" : "cavalier", "amount" : 1 } ], | ||||
| 						}, | ||||
| 						"changeCreatures" : { | ||||
| 							"cavalier" : "champion" | ||||
| 						} | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 136 | ||||
| 					}, | ||||
| 				], | ||||
|  | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { | ||||
| 							"creatures" : [ { "type" : "cavalier", "amount" : 1 } ], | ||||
| 						}, | ||||
| 						"message" : 138, | ||||
| 						"movePoints" : 400, | ||||
| 						"bonuses" : [ { "type" : "LAND_MOVEMENT", "val" : 400, "duration" : "ONE_WEEK"} ], | ||||
| 						"changeCreatures" : { | ||||
| 							"cavalier" : "champion" | ||||
| 						} | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 137, | ||||
| 						"movePoints" : 400, | ||||
| 						"bonuses" : [ { "type" : "LAND_MOVEMENT", "val" : 400, "duration" : "ONE_WEEK"} ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"temple" : { | ||||
| 		"index" : 96, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSANC"], | ||||
| 				"visit" : ["TEMPLE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"temple" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 141, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 140, | ||||
| 						"limiter" : { "dayOfWeek" : 7 }, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 2, "duration" : "ONE_BATTLE", "description" : 97 } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 140, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 96 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"rallyFlag" : { | ||||
| 		"index" : 64, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFLAG"], | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"rallyFlag" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 100, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 100, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 111, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 110, | ||||
| 						"movePoints" : 400, | ||||
| 						"bonuses" : [  | ||||
| 							{ "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 102 }, | ||||
| 							{ "type" : "LUCK", "val" : 1, "duration" : "ONE_BATTLE", "description" : 102 } | ||||
| 						] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"wateringHole" : { | ||||
| 		"index" : 110, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MORALE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"wateringHole" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit"	: 1, | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 167, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 166, | ||||
| 						"movePoints" : 400, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : 1, "duration" : "ONE_BATTLE", "description" : 100 } ] | ||||
| 					} | ||||
| 				] | ||||
| 			}  | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										364
									
								
								config/objects/rewardableOncePerHero.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								config/objects/rewardableOncePerHero.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,364 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" and have their entire configuration in this config | ||||
|  | ||||
| 	"arena" : { | ||||
| 		"index" : 4, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPAREN"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"arena" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 3000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 3000, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onSelectMessage" : 0, | ||||
| 				"onVisitedMessage" : 1, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectPlayer", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"primary" : { "attack" : 2 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"primary" : { "defence" : 2 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"marlettoTower" : { | ||||
| 		"index" : 23, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSWAR"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"marlettoTower" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
|  | ||||
| 				"onVisitedMessage" : 40, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 39, | ||||
| 						"primary" : { "defence" : 1 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"gardenOfRevelation" : { | ||||
| 		"index" : 32, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPGARD"], | ||||
| 				"visit" : ["GETPROTECTION"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"gardenOfRevelation" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 60, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 59, | ||||
| 						"primary" : { "knowledge" : 1 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"libraryOfEnlightenment" : { | ||||
| 		"index" : 41, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"libraryOfEnlightenment" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 12000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 12000, | ||||
| 					"rarity"	: 20 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 67, | ||||
| 				"onEmptyMessage" : 68, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { | ||||
| 							"anyOf" : [ | ||||
| 								{ "heroLevel" : 10 }, | ||||
| 								{ "heroLevel" :  8, "secondary" : { "diplomacy" : 1 } }, | ||||
| 								{ "heroLevel" :  6, "secondary" : { "diplomacy" : 2 } }, | ||||
| 								{ "heroLevel" :  4, "secondary" : { "diplomacy" : 3 } } | ||||
| 							] | ||||
| 						}, | ||||
| 						"message" : 59, | ||||
| 						"primary" : {  | ||||
| 							"attack" : 2, | ||||
| 							"defence" : 2, | ||||
| 							"spellpower" : 2, | ||||
| 							"knowledge" : 2 | ||||
| 						} | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"mercenaryCamp" : { | ||||
| 		"index" : 51, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMERC"], | ||||
| 				"visit" : ["NOMAD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"mercenaryCamp" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 			 | ||||
| 				"onVisitedMessage" : 81, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 80, | ||||
| 						"primary" : { "attack" : 1 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"starAxis" :{ | ||||
| 		"index" : 61, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSTAR"], | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"starAxis" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 101, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 100, | ||||
| 						"primary" : { "spellpower" : 1 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"treeOfKnowledge" : { | ||||
| 		"index" : 102, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"treeOfKnowledge" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2500, | ||||
| 				"rmg" : { | ||||
| 					"mapLimit"	: 100, | ||||
| 					"value"		: 2500, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
|  | ||||
| 				"onEmpty" : [ | ||||
| 					{ | ||||
| 						"message" : 150, | ||||
| 						"appearChance" : { "min" : 34, "max" : 67 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 152, | ||||
| 						"appearChance" : { "min" : 67, "max" : 67 } | ||||
| 					} | ||||
| 				], | ||||
| 				"onVisitedMessage" : 147, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"canRefuse" : true, | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 148, | ||||
| 						"appearChance" : { "max" : 34 }, | ||||
| 						"gainedLevels" : 1 | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 149, | ||||
| 						"appearChance" : { "min" : 34, "max" : 67 }, | ||||
| 						"limiter" : { "resources" : { "gold" : 2000 } }, | ||||
| 						"resources" : { "gold" : -2000 }, | ||||
| 						"gainedLevels" : 1 | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 151, | ||||
| 						"appearChance" : { "min" : 67 }, | ||||
| 						"limiter" : { "resources" : { "gems" : 10 } }, | ||||
| 						"resources" : { "gems" : -10 }, | ||||
| 						"gainedLevels" : 1 | ||||
| 					}, | ||||
| 				]	 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"schoolOfMagic" : { | ||||
| 		"index" : 47, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMAGI"], | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"schoolOfMagic" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1000, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onSelectMessage" : 71, | ||||
| 				"onVisitedMessage" : 72, | ||||
| 				"onEmptyMessage" : 73, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectPlayer", | ||||
| 				"canRefuse" : true, | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { "resources" : { "gold" : 1000 } }, | ||||
| 						"resources" : { "gold" : -1000 }, | ||||
| 						"primary" : { "spellpower" : 1 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"limiter" : { "resources" : { "gold" : 1000 } }, | ||||
| 						"resources" : { "gold" : -1000 }, | ||||
| 						"primary" : { "knowledge" : 1 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"schoolOfWar" : { | ||||
| 		"index" : 107, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPSWAR"], | ||||
| 				"visit" : ["MILITARY"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"schoolOfWar" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1000, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
|  | ||||
| 				"onSelectMessage" : 158, | ||||
| 				"onVisitedMessage" : 159, | ||||
| 				"onEmptyMessage" : 160, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectPlayer", | ||||
| 				"canRefuse" : true, | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { "resources" : { "gold" : 1000 } }, | ||||
| 						"resources" : { "gold" : -1000 }, | ||||
| 						"primary" : { "attack" : 1 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"limiter" : { "resources" : { "gold" : 1000 } }, | ||||
| 						"resources" : { "gold" : -1000 }, | ||||
| 						"primary" : { "defence" : 1 } | ||||
| 					} | ||||
| 				]	 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"learningStone" : { | ||||
| 		"index" : 100, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPLEAR"], | ||||
| 				"visit" : ["GAZEBO"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"learningStone" : {  | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 200 | ||||
| 				}, | ||||
|  | ||||
| 				"onVisitedMessage" : 144, | ||||
| 				"visitMode" : "hero", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 143, | ||||
| 						"heroExperience" : 1000 | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										199
									
								
								config/objects/rewardableOncePerWeek.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								config/objects/rewardableOncePerWeek.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" and have their entire configuration in this config | ||||
| 	"magicWell" : { | ||||
| 		"index" :49, | ||||
| 		"handler" : "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"magicWell" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 250, | ||||
| 				"rmg" : { | ||||
| 					"zoneLimit" : 1, | ||||
| 					"value"		: 250, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onEmptyMessage" : 79, | ||||
| 				"onVisitedMessage" : 78, | ||||
| 				"visitMode" : "bonus", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { | ||||
| 							"noneOf" : [ { "manaPercentage" : 100 } ] | ||||
| 						}, | ||||
| 						"bonuses" : [ { "type" : "NONE", "duration" : "ONE_DAY"} ], | ||||
| 						"message" : 77, | ||||
| 						"manaPercentage" : 100 | ||||
| 					} | ||||
| 				]	 | ||||
| 			}, | ||||
| 		} | ||||
| 	}, | ||||
| 	"magicSpring" : { | ||||
| 		"index" : 48, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPFOUN"], | ||||
| 				"visit" : ["FAERIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"magicSpring" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				//banned due to problems with 2 viistable offsets | ||||
| 				//"rmg" : { | ||||
| 				//	"zoneLimit"	: 1, | ||||
| 				//	"value"		: 500, | ||||
| 				//	"rarity"	: 50 | ||||
| 				//}, | ||||
| 				 | ||||
| 				"onEmptyMessage" : 76, | ||||
| 				"onVisitedMessage" : 75, | ||||
| 				"resetParameters" : { | ||||
| 					"period" : 7, | ||||
| 					"visitors" : true | ||||
| 				}, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { | ||||
| 							"noneOf" : [ { "manaPercentage" : 200 } ] | ||||
| 						}, | ||||
| 						"message" : 74, | ||||
| 						"manaPercentage" : 200 | ||||
| 					} | ||||
| 				]				 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"mysticalGarden" : { | ||||
| 		"index" : 55, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPLEPR"], | ||||
| 				"visit" : ["EXPERNCE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"mysticalGarden" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 93, | ||||
| 				"resetParameters" : { | ||||
| 					"period" : 7, | ||||
| 					"visitors" : true, | ||||
| 					"rewards" : true | ||||
| 				}, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 92, | ||||
| 						"appearChance" : { "max" : 50 }, | ||||
| 						"resources" : { "gems" : 5 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 92, | ||||
| 						"appearChance" : { "min" : 50 }, | ||||
| 						"resources" : { "gold" : 500 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"windmill" :{ | ||||
| 		"index" : 112, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPWIND"], | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"windmill" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 80 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 169, | ||||
| 				"resetParameters" : { | ||||
| 					"period" : 7, | ||||
| 					"visitors" : true, | ||||
| 					"rewards" : true | ||||
| 				}, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 170, | ||||
| 						"resources" : [ | ||||
| 							{ | ||||
| 								"list" : [ "ore", "mercury", "gems", "sulfur", "crystal" ], | ||||
| 								"min" : 3, | ||||
| 								"max" : 6 | ||||
| 							} | ||||
| 						] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"waterWheel" : { | ||||
| 		"index" : 109, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPMILL"], | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"waterWheel" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 750, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 750, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 165, | ||||
| 				"resetParameters" : { | ||||
| 					"period" : 7, | ||||
| 					"visitors" : true | ||||
| 				}, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"limiter" : { "daysPassed" : 8 }, | ||||
| 						"message" : 164, | ||||
| 						"resources" : { "gold" : 1000 } | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 164, | ||||
| 						"resources" : { "gold" : 500 } | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										185
									
								
								config/objects/rewardableOnceVisitable.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								config/objects/rewardableOnceVisitable.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" and have their entire configuration in this config | ||||
|  | ||||
| 	"leanTo" :{ | ||||
| 		"index" : 39, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"leanTo" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 65, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 64, | ||||
| 						"resources" : [ | ||||
| 							{ | ||||
| 								"list" : [ "wood", "ore", "mercury", "gems", "sulfur", "crystal" ], | ||||
| 								"min" : 1, | ||||
| 								"max" : 5 | ||||
| 							} | ||||
| 						] | ||||
| 					} | ||||
| 				]				 | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"corpse" :{ | ||||
| 		"index" : 22, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["MYSTERY"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"corpse" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 38, | ||||
| 				"blockedVisitable" : true, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 10 }, | ||||
| 						"message" : 37, | ||||
| 						"artifacts" : [ { "class" : "TREASURE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 10, "max" : 20 }, | ||||
| 						"message" : 37, | ||||
| 						"artifacts" : [ { "class" : "MINOR" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 20, "max" : 100 }, | ||||
| 						"message" : 38, | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"wagon" :{ | ||||
| 		"index" : 105, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"wagon" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 500, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onVisitedMessage" : 156, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 20 }, | ||||
| 						"message" : 155, | ||||
| 						"artifacts" : [ { "class" : "TREASURE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 20, "max" : 40 }, | ||||
| 						"message" : 155, | ||||
| 						"artifacts" : [ { "class" : "MINOR" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 154, | ||||
| 						"appearChance" : { "min" : 40, "max" : 90 }, | ||||
| 						"resources" : [ | ||||
| 							{ | ||||
| 								"list" : [ "wood", "ore", "mercury", "gems", "sulfur", "crystal" ], | ||||
| 								"min" : 2, | ||||
| 								"max" : 5 | ||||
| 							}, | ||||
| 						] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 90, "max" : 100 }, | ||||
| 						"message" : 156, | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"warriorTomb" : { | ||||
| 		"index" : 108, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GRAVEYARD"] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"warriorTomb" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 6000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 6000, | ||||
| 					"rarity"	: 20 | ||||
| 				}, | ||||
| 				 | ||||
| 				"onSelectMessage" : 161, | ||||
| 				"visitMode" : "once", | ||||
| 				"selectMode" : "selectFirst", | ||||
|  | ||||
| 				"onVisited" : [ | ||||
| 					{ | ||||
| 						"message" : 163, | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : -3, "duration" : "ONE_BATTLE" } ] | ||||
| 					} | ||||
| 				], | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 30 }, | ||||
| 						"message" : 162, | ||||
| 						"artifacts" : [ { "class" : "TREASURE" } ], | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : -3, "duration" : "ONE_BATTLE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 30, "max" : 80 }, | ||||
| 						"message" : 162, | ||||
| 						"artifacts" : [ { "class" : "MINOR" } ], | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : -3, "duration" : "ONE_BATTLE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 80, "max" : 95 }, | ||||
| 						"message" : 162, | ||||
| 						"artifacts" : [ { "class" : "MAJOR" } ], | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : -3, "duration" : "ONE_BATTLE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 95 }, | ||||
| 						"message" : 162, | ||||
| 						"artifacts" : [ { "class" : "RELIC" } ], | ||||
| 						"bonuses" : [ { "type" : "MORALE", "val" : -3, "duration" : "ONE_BATTLE" } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										267
									
								
								config/objects/rewardablePickable.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								config/objects/rewardablePickable.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | ||||
| { | ||||
| 	/// These are objects that covered by concept of "configurable object" and have their entire configuration in this config | ||||
|  | ||||
| 	"campfire" :{ | ||||
| 		"index" : 12, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"ambient" : ["LOOPCAMP"], | ||||
| 				"visit" : ["EXPERNCE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"campfire" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 2000, | ||||
| 					"rarity"	: 500 | ||||
| 				}, | ||||
| 				 | ||||
| 				"blockedVisitable" : true, | ||||
| 				"visitMode" : "unlimited", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 23, | ||||
| 						"removeObject" : true, | ||||
| 						"resources" : [ | ||||
| 							{ | ||||
| 								"list" : [ "wood", "ore", "mercury", "gems", "sulfur", "crystal" ], | ||||
| 								"min" : 4, | ||||
| 								"max" : 6 | ||||
| 							}, | ||||
| 							{ | ||||
| 								"type" : "gold", | ||||
| 								"min" : 400, | ||||
| 								"max" : 600 | ||||
| 							} | ||||
| 						] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"flotsam" :{ | ||||
| 		"index" : 29, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["GENIE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"flotsam" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 2000, | ||||
| 					"rarity"	: 100 | ||||
| 				}, | ||||
| 				 | ||||
| 				"blockedVisitable" : true, | ||||
| 				"visitMode" : "unlimited", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"message" : 51, | ||||
| 						"appearChance" : { "max" : 25 }, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 52, | ||||
| 						"appearChance" : { "min" : 25, "max" : 50 }, | ||||
| 						"removeObject" : true, | ||||
| 						"resources" : { | ||||
| 							"wood" : 5 | ||||
| 						} | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 53, | ||||
| 						"appearChance" : { "min" : 50, "max" : 75 }, | ||||
| 						"removeObject" : true, | ||||
| 						"resources" : { | ||||
| 							"wood" : 5, | ||||
| 							"gold" : 200 | ||||
| 						} | ||||
| 					}, | ||||
| 					{ | ||||
| 						"message" : 54, | ||||
| 						"appearChance" : { "min" : 75 }, | ||||
| 						"removeObject" : true, | ||||
| 						"resources" : { | ||||
| 							"wood" : 10, | ||||
| 							"gold" : 500 | ||||
| 						} | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"seaChest" :{ | ||||
| 		"index" : 82, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["CHEST"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"seaChest" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 500 | ||||
| 				}, | ||||
| 				 | ||||
| 				"blockedVisitable" : true, | ||||
| 				"visitMode" : "unlimited", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 20 }, | ||||
| 						"message" : 116, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 20, "max" : 30 }, | ||||
| 						"message" : 117, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ | ||||
| 							{ "class" : "TREASURE" } | ||||
| 						], | ||||
| 						"resources" : { | ||||
| 							"gold" : 1000 | ||||
| 						} | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 30 }, | ||||
| 						"message" : 118, | ||||
| 						"removeObject" : true, | ||||
| 						"resources" : { | ||||
| 							"gold" : 1500 | ||||
| 						} | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"shipwreckSurvivor" : { | ||||
| 		"index" : 86, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["TREASURE"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"shipwreckSurvivor" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 1500, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 50 | ||||
| 				}, | ||||
|  | ||||
| 				"blockedVisitable" : true, | ||||
| 				"visitMode" : "unlimited", | ||||
| 				"selectMode" : "selectFirst", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 55 }, | ||||
| 						"message" : 125, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ { "class" : "TREASURE" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 55, "max" : 75 }, | ||||
| 						"message" : 125, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ { "class" : "MINOR" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 75, "max" : 95 }, | ||||
| 						"message" : 125, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ { "class" : "MAJOR" } ] | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 95 }, | ||||
| 						"message" : 125, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ { "class" : "RELIC" } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| 	"treasureChest" : { | ||||
| 		"index" : 101, | ||||
| 		"handler": "configurable", | ||||
| 		"base" : { | ||||
| 			"sounds" : { | ||||
| 				"visit" : ["CHEST"], | ||||
| 				"removal" : [ "PICKUP01", "PICKUP02", "PICKUP03", "PICKUP04", "PICKUP05", "PICKUP06", "PICKUP07" ] | ||||
| 			} | ||||
| 		}, | ||||
| 		"types" : { | ||||
| 			"treasureChest" : { | ||||
| 				"index" : 0, | ||||
| 				"aiValue" : 2000, | ||||
| 				"rmg" : { | ||||
| 					"value"		: 1500, | ||||
| 					"rarity"	: 1000 | ||||
| 				}, | ||||
| 				 | ||||
| 				"blockedVisitable" : true, | ||||
| 				"onSelectMessage" : 146, | ||||
| 				"visitMode" : "unlimited", | ||||
| 				"selectMode" : "selectPlayer", | ||||
| 				"rewards" : [ | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 33 }, | ||||
| 						"resources" : { "gold" : 2000 }, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "max" : 33 }, | ||||
| 						"gainedExp" : 1500, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 33, "max" : 65 }, | ||||
| 						"resources" : { "gold" : 1500 }, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 33, "max" : 65 }, | ||||
| 						"gainedExp" : 1000, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 65, "max" : 95 }, | ||||
| 						"resources" : { "gold" : 1000 }, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 65, "max" : 95 }, | ||||
| 						"gainedExp" : 500, | ||||
| 						"removeObject" : true, | ||||
| 					}, | ||||
| 					{ | ||||
| 						"appearChance" : { "min" : 95 }, | ||||
| 						"message" : 145, | ||||
| 						"removeObject" : true, | ||||
| 						"artifacts" : [ { "class" : "TREASURE" } ] | ||||
| 					} | ||||
| 				] | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -142,9 +142,6 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst | ||||
| 		case GENERAL_TXT: | ||||
| 			dst = VLC->generaltexth->translate("core.genrltxt", ser); | ||||
| 			break; | ||||
| 		case XTRAINFO_TXT: | ||||
| 			dst = VLC->generaltexth->translate("core.xtrainfo", ser); | ||||
| 			break; | ||||
| 		case RES_NAMES: | ||||
| 			dst = VLC->generaltexth->translate("core.restypes", ser); | ||||
| 			break; | ||||
|   | ||||
| @@ -409,7 +409,6 @@ CGeneralTextHandler::CGeneralTextHandler(): | ||||
| 	hcommands        (*this, "core.hallinfo" ), | ||||
| 	fcommands        (*this, "core.castinfo" ), | ||||
| 	advobtxt         (*this, "core.advevent" ), | ||||
| 	xtrainfo         (*this, "core.xtrainfo" ), | ||||
| 	restypes         (*this, "core.restypes" ), | ||||
| 	randsign         (*this, "core.randsign" ), | ||||
| 	overview         (*this, "core.overview" ), | ||||
| @@ -439,7 +438,6 @@ CGeneralTextHandler::CGeneralTextHandler(): | ||||
| 	readToVector("core.hallinfo", "DATA/HALLINFO.TXT" ); | ||||
| 	readToVector("core.castinfo", "DATA/CASTINFO.TXT" ); | ||||
| 	readToVector("core.advevent", "DATA/ADVEVENT.TXT" ); | ||||
| 	readToVector("core.xtrainfo", "DATA/XTRAINFO.TXT" ); | ||||
| 	readToVector("core.restypes", "DATA/RESTYPES.TXT" ); | ||||
| 	readToVector("core.randsign", "DATA/RANDSIGN.TXT" ); | ||||
| 	readToVector("core.crgen1",   "DATA/CRGEN1.TXT"   ); | ||||
|   | ||||
| @@ -212,7 +212,6 @@ public: | ||||
|  | ||||
| 	//objects | ||||
| 	LegacyTextContainer advobtxt; | ||||
| 	LegacyTextContainer xtrainfo; | ||||
| 	LegacyTextContainer restypes; //names of resources | ||||
| 	LegacyTextContainer randsign; | ||||
| 	LegacyTextContainer seerEmpty; | ||||
|   | ||||
| @@ -260,6 +260,21 @@ bool JsonNode::isNumber() const | ||||
| 	return type == JsonType::DATA_INTEGER || type == JsonType::DATA_FLOAT; | ||||
| } | ||||
|  | ||||
| bool JsonNode::isString() const | ||||
| { | ||||
| 	return type == JsonType::DATA_STRING; | ||||
| } | ||||
|  | ||||
| bool JsonNode::isVector() const | ||||
| { | ||||
| 	return type == JsonType::DATA_VECTOR; | ||||
| } | ||||
|  | ||||
| bool JsonNode::isStruct() const | ||||
| { | ||||
| 	return type == JsonType::DATA_STRUCT; | ||||
| } | ||||
|  | ||||
| bool JsonNode::containsBaseData() const | ||||
| { | ||||
| 	switch(type) | ||||
| @@ -796,7 +811,12 @@ bool JsonUtils::parseBonus(const JsonNode &ability, Bonus *b) | ||||
| 	b->sid = static_cast<si32>(ability["sourceID"].Float()); | ||||
|  | ||||
| 	if(!ability["description"].isNull()) | ||||
| 		b->description = ability["description"].String(); | ||||
| 	{ | ||||
| 		if (ability["description"].isString()) | ||||
| 			b->description = ability["description"].String(); | ||||
| 		if (ability["description"].isNumber()) | ||||
| 			b->description = VLC->generaltexth->translate("core.arraytxt", ability["description"].Integer()); | ||||
| 	} | ||||
|  | ||||
| 	value = &ability["effectRange"]; | ||||
| 	if (!value->isNull()) | ||||
|   | ||||
| @@ -83,6 +83,9 @@ public: | ||||
|  | ||||
| 	bool isNull() const; | ||||
| 	bool isNumber() const; | ||||
| 	bool isString() const; | ||||
| 	bool isVector() const; | ||||
| 	bool isStruct() const; | ||||
| 	/// true if node contains not-null data that cannot be extended via merging | ||||
| 	/// used for generating common base node from multiple nodes (e.g. bonuses) | ||||
| 	bool containsBaseData() const; | ||||
|   | ||||
| @@ -1178,7 +1178,7 @@ namespace ObjProperty | ||||
| 		BANK_DAYCOUNTER, BANK_RESET, BANK_CLEAR, | ||||
|  | ||||
| 		//object with reward | ||||
| 		REWARD_RESET, REWARD_SELECT | ||||
| 		REWARD_RANDOMIZE, REWARD_SELECT, REWARD_CLEARED | ||||
| 	}; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -96,7 +96,7 @@ struct DLL_LINKAGE MetaString | ||||
| private: | ||||
| 	enum EMessage {TEXACT_STRING, TLOCAL_STRING, TNUMBER, TREPLACE_ESTRING, TREPLACE_LSTRING, TREPLACE_NUMBER, TREPLACE_PLUSNUMBER}; | ||||
| public: | ||||
| 	enum {GENERAL_TXT=1, XTRAINFO_TXT, OBJ_NAMES, RES_NAMES, ART_NAMES, ARRAY_TXT, CRE_PL_NAMES, CREGENS, MINE_NAMES, | ||||
| 	enum {GENERAL_TXT=1, OBJ_NAMES, RES_NAMES, ART_NAMES, ARRAY_TXT, CRE_PL_NAMES, CREGENS, MINE_NAMES, | ||||
| 		MINE_EVNTS, ADVOB_TXT, ART_EVNTS, SPELL_NAME, SEC_SKILL_NAME, CRE_SING_NAMES, CREGENS4, COLOR, ART_DESCR, JK_TXT}; | ||||
|  | ||||
| 	std::vector<ui8> message; //vector of EMessage | ||||
|   | ||||
| @@ -54,7 +54,6 @@ CObjectClassesHandler::CObjectClassesHandler() | ||||
| 	SET_HANDLER("artifact", CGArtifact); | ||||
| 	SET_HANDLER("blackMarket", CGBlackMarket); | ||||
| 	SET_HANDLER("boat", CGBoat); | ||||
| 	SET_HANDLER("bonusingObject", CGBonusingObject); | ||||
| 	SET_HANDLER("borderGate", CGBorderGate); | ||||
| 	SET_HANDLER("borderGuard", CGBorderGuard); | ||||
| 	SET_HANDLER("monster", CGCreature); | ||||
| @@ -65,15 +64,11 @@ CObjectClassesHandler::CObjectClassesHandler() | ||||
| 	SET_HANDLER("keymaster", CGKeymasterTent); | ||||
| 	SET_HANDLER("lighthouse", CGLighthouse); | ||||
| 	SET_HANDLER("magi", CGMagi); | ||||
| 	SET_HANDLER("magicSpring", CGMagicSpring); | ||||
| 	SET_HANDLER("magicWell", CGMagicWell); | ||||
| 	SET_HANDLER("market", CGMarket); | ||||
| 	SET_HANDLER("mine", CGMine); | ||||
| 	SET_HANDLER("obelisk", CGObelisk); | ||||
| 	SET_HANDLER("observatory", CGObservatory); | ||||
| 	SET_HANDLER("onceVisitable", CGOnceVisitable); | ||||
| 	SET_HANDLER("pandora", CGPandoraBox); | ||||
| 	SET_HANDLER("pickable", CGPickable); | ||||
| 	SET_HANDLER("prison", CGHeroInstance); | ||||
| 	SET_HANDLER("questGuard", CGQuestGuard); | ||||
| 	SET_HANDLER("resource", CGResource); | ||||
| @@ -87,8 +82,6 @@ CObjectClassesHandler::CObjectClassesHandler() | ||||
| 	SET_HANDLER("subterraneanGate", CGSubterraneanGate); | ||||
| 	SET_HANDLER("whirlpool", CGWhirlpool); | ||||
| 	SET_HANDLER("university", CGUniversity); | ||||
| 	SET_HANDLER("oncePerHero", CGVisitableOPH); | ||||
| 	SET_HANDLER("oncePerWeek", CGVisitableOPW); | ||||
| 	SET_HANDLER("witch", CGWitchHut); | ||||
| 	SET_HANDLER("terrain", CGTerrainPatch); | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include "../CRandomGenerator.h" | ||||
| #include "../StringConstants.h" | ||||
| #include "../CCreatureHandler.h" | ||||
| #include "../CModHandler.h" | ||||
| #include "JsonRandom.h" | ||||
| #include "../IGameCallback.h" | ||||
|  | ||||
| @@ -45,11 +46,118 @@ void CRandomRewardObjectInfo::init(const JsonNode & objectConfig) | ||||
| 	parameters = objectConfig; | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRandomGenerator & rng) const | ||||
| TRewardLimitersList CRandomRewardObjectInfo::configureSublimiters(CRewardableObject * object, CRandomGenerator & rng, const JsonNode & source) const | ||||
| { | ||||
| 	std::map<si32, si32> thrownDice; | ||||
| 	TRewardLimitersList result; | ||||
| 	for (const auto & input : source.Vector()) | ||||
| 	{ | ||||
| 		auto newLimiter = std::make_shared<CRewardLimiter>(); | ||||
|  | ||||
| 	for (const JsonNode & reward : parameters["rewards"].Vector()) | ||||
| 		configureLimiter(object, rng, *newLimiter, input); | ||||
|  | ||||
| 		result.push_back(newLimiter); | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureLimiter(CRewardableObject * object, CRandomGenerator & rng, CRewardLimiter & limiter, const JsonNode & source) const | ||||
| { | ||||
| 	std::vector<SpellID> spells; | ||||
| 	for (size_t i=0; i<6; i++) | ||||
| 		IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i)); | ||||
|  | ||||
|  | ||||
| 	limiter.dayOfWeek = JsonRandom::loadValue(source["dayOfWeek"], rng); | ||||
| 	limiter.daysPassed = JsonRandom::loadValue(source["daysPassed"], rng); | ||||
| 	limiter.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng); | ||||
| 	limiter.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng) | ||||
| 					 + JsonRandom::loadValue(source["minLevel"], rng); // VCMI 1.1 compatibilty | ||||
|  | ||||
| 	limiter.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng); | ||||
| 	limiter.manaPoints = JsonRandom::loadValue(source["manaPoints"], rng); | ||||
|  | ||||
| 	limiter.resources = JsonRandom::loadResources(source["resources"], rng); | ||||
|  | ||||
| 	limiter.primary = JsonRandom::loadPrimary(source["primary"], rng); | ||||
| 	limiter.secondary = JsonRandom::loadSecondary(source["secondary"], rng); | ||||
| 	limiter.artifacts = JsonRandom::loadArtifacts(source["spells"], rng); | ||||
| 	limiter.spells  = JsonRandom::loadSpells(source["artifacts"], rng, spells); | ||||
| 	limiter.creatures = JsonRandom::loadCreatures(source["creatures"], rng); | ||||
|  | ||||
| 	limiter.allOf  = configureSublimiters(object, rng, source["allOf"] ); | ||||
| 	limiter.anyOf  = configureSublimiters(object, rng, source["anyOf"] ); | ||||
| 	limiter.noneOf = configureSublimiters(object, rng, source["noneOf"] ); | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureReward(CRewardableObject * object, CRandomGenerator & rng, CRewardInfo & reward, const JsonNode & source) const | ||||
| { | ||||
| 	reward.resources = JsonRandom::loadResources(source["resources"], rng); | ||||
|  | ||||
| 	reward.heroExperience = JsonRandom::loadValue(source["heroExperience"], rng) | ||||
| 						  + JsonRandom::loadValue(source["gainedExp"], rng); // VCMI 1.1 compatibilty | ||||
|  | ||||
| 	reward.heroLevel = JsonRandom::loadValue(source["heroLevel"], rng) | ||||
| 						+ JsonRandom::loadValue(source["gainedLevels"], rng); // VCMI 1.1 compatibilty | ||||
|  | ||||
| 	reward.manaDiff = JsonRandom::loadValue(source["manaPoints"], rng); | ||||
| 	reward.manaOverflowFactor = JsonRandom::loadValue(source["manaOverflowFactor"], rng); | ||||
| 	reward.manaPercentage = JsonRandom::loadValue(source["manaPercentage"], rng, -1); | ||||
|  | ||||
| 	reward.movePoints = JsonRandom::loadValue(source["movePoints"], rng); | ||||
| 	reward.movePercentage = JsonRandom::loadValue(source["movePercentage"], rng, -1); | ||||
|  | ||||
| 	reward.removeObject = source["removeObject"].Bool(); | ||||
| 	reward.bonuses = JsonRandom::loadBonuses(source["bonuses"]); | ||||
|  | ||||
| 	for (auto & bonus : reward.bonuses) | ||||
| 	{ | ||||
| 		bonus.source = Bonus::OBJECT; | ||||
| 		bonus.sid = object->ID; | ||||
| 		//TODO: bonus.description = object->getObjectName(); | ||||
| 		if (bonus.type == Bonus::MORALE) | ||||
| 			reward.extraComponents.push_back(Component(Component::MORALE, 0, bonus.val, 0)); | ||||
| 		if (bonus.type == Bonus::LUCK) | ||||
| 			reward.extraComponents.push_back(Component(Component::LUCK, 0, bonus.val, 0)); | ||||
| 	} | ||||
|  | ||||
| 	reward.primary = JsonRandom::loadPrimary(source["primary"], rng); | ||||
| 	reward.secondary = JsonRandom::loadSecondary(source["secondary"], rng); | ||||
|  | ||||
| 	std::vector<SpellID> spells; | ||||
| 	for (size_t i=0; i<6; i++) | ||||
| 		IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i)); | ||||
|  | ||||
| 	reward.artifacts = JsonRandom::loadArtifacts(source["artifacts"], rng); | ||||
| 	reward.spells = JsonRandom::loadSpells(source["spells"], rng, spells); | ||||
| 	reward.creatures = JsonRandom::loadCreatures(source["creatures"], rng); | ||||
|  | ||||
| 	for ( auto node : source["changeCreatures"].Struct() ) | ||||
| 	{ | ||||
| 		CreatureID from (VLC->modh->identifiers.getIdentifier (node.second.meta, "creature", node.first) .get()); | ||||
| 		CreatureID dest (VLC->modh->identifiers.getIdentifier (node.second.meta, "creature", node.second.String()).get()); | ||||
|  | ||||
| 		reward.extraComponents.push_back(Component(Component::CREATURE, dest.getNum(), 0, 0)); | ||||
|  | ||||
| 		reward.creaturesChange[from] = dest; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureResetInfo(CRewardableObject * object, CRandomGenerator & rng, CRewardResetInfo & resetParameters, const JsonNode & source) const | ||||
| { | ||||
| 	resetParameters.period   = static_cast<ui32>(source["period"].Float()); | ||||
| 	resetParameters.visitors = source["visitors"].Bool(); | ||||
| 	resetParameters.rewards  = source["rewards"].Bool(); | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureRewards( | ||||
| 		CRewardableObject * object, | ||||
| 		CRandomGenerator & rng, const | ||||
| 		JsonNode & source, | ||||
| 		std::map<si32, si32> & thrownDice, | ||||
| 		CRewardVisitInfo::ERewardEventType event ) const | ||||
| { | ||||
| 	for (const JsonNode & reward : source.Vector()) | ||||
| 	{ | ||||
| 		if (!reward["appearChance"].isNull()) | ||||
| 		{ | ||||
| @@ -57,7 +165,7 @@ void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRando | ||||
| 			si32 diceID = static_cast<si32>(chance["dice"].Float()); | ||||
|  | ||||
| 			if (thrownDice.count(diceID) == 0) | ||||
| 				thrownDice[diceID] = rng.getIntRange(1, 100)(); | ||||
| 				thrownDice[diceID] = rng.getIntRange(0, 99)(); | ||||
|  | ||||
| 			if (!chance["min"].isNull()) | ||||
| 			{ | ||||
| @@ -68,61 +176,59 @@ void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRando | ||||
| 			if (!chance["max"].isNull()) | ||||
| 			{ | ||||
| 				int max = static_cast<int>(chance["max"].Float()); | ||||
| 				if (max < thrownDice[diceID]) | ||||
| 				if (max <= thrownDice[diceID]) | ||||
| 					continue; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const JsonNode & limiter = reward["limiter"]; | ||||
| 		CVisitInfo info; | ||||
| 		// load limiter | ||||
| 		info.limiter.numOfGrants = JsonRandom::loadValue(limiter["numOfGrants"], rng); | ||||
| 		info.limiter.dayOfWeek = JsonRandom::loadValue(limiter["dayOfWeek"], rng); | ||||
| 		info.limiter.minLevel = JsonRandom::loadValue(limiter["minLevel"], rng); | ||||
| 		info.limiter.resources = JsonRandom::loadResources(limiter["resources"], rng); | ||||
|  | ||||
| 		info.limiter.primary = JsonRandom::loadPrimary(limiter["primary"], rng); | ||||
| 		info.limiter.secondary = JsonRandom::loadSecondary(limiter["secondary"], rng); | ||||
| 		info.limiter.artifacts = JsonRandom::loadArtifacts(limiter["artifacts"], rng); | ||||
| 		info.limiter.creatures = JsonRandom::loadCreatures(limiter["creatures"], rng); | ||||
|  | ||||
| 		info.reward.resources = JsonRandom::loadResources(reward["resources"], rng); | ||||
|  | ||||
| 		info.reward.gainedExp = JsonRandom::loadValue(reward["gainedExp"], rng); | ||||
| 		info.reward.gainedLevels = JsonRandom::loadValue(reward["gainedLevels"], rng); | ||||
|  | ||||
| 		info.reward.manaDiff = JsonRandom::loadValue(reward["manaPoints"], rng); | ||||
| 		info.reward.manaPercentage = JsonRandom::loadValue(reward["manaPercentage"], rng, -1); | ||||
|  | ||||
| 		info.reward.movePoints = JsonRandom::loadValue(reward["movePoints"], rng); | ||||
| 		info.reward.movePercentage = JsonRandom::loadValue(reward["movePercentage"], rng, -1); | ||||
| 		 | ||||
| 		info.reward.removeObject = reward["removeObject"].Bool(); | ||||
|  | ||||
| 		//FIXME: compile this line on Visual | ||||
| 		//info.reward.bonuses = JsonRandom::loadBonuses(reward["bonuses"]); | ||||
|  | ||||
| 		info.reward.primary = JsonRandom::loadPrimary(reward["primary"], rng); | ||||
| 		info.reward.secondary = JsonRandom::loadSecondary(reward["secondary"], rng); | ||||
|  | ||||
| 		std::vector<SpellID> spells; | ||||
| 		for (size_t i=0; i<6; i++) | ||||
| 			IObjectInterface::cb->getAllowedSpells(spells, static_cast<ui16>(i)); | ||||
|  | ||||
| 		info.reward.artifacts = JsonRandom::loadArtifacts(reward["artifacts"], rng); | ||||
| 		info.reward.spells = JsonRandom::loadSpells(reward["spells"], rng, spells); | ||||
| 		info.reward.creatures = JsonRandom::loadCreatures(reward["creatures"], rng); | ||||
| 		CRewardVisitInfo info; | ||||
| 		configureLimiter(object, rng, info.limiter, reward["limiter"]); | ||||
| 		configureReward(object, rng, info.reward, reward); | ||||
|  | ||||
| 		info.visitType = event; | ||||
| 		info.message = loadMessage(reward["message"]); | ||||
| 		info.selectChance = JsonRandom::loadValue(reward["selectChance"], rng); | ||||
| 		 | ||||
|  | ||||
| 		for (const auto & artifact : info.reward.artifacts ) | ||||
| 			info.message.addReplacement(MetaString::ART_NAMES, artifact.getNum()); | ||||
|  | ||||
| 		for (const auto & artifact : info.reward.spells ) | ||||
| 			info.message.addReplacement(MetaString::SPELL_NAME, artifact.getNum()); | ||||
|  | ||||
| 		object->info.push_back(info); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRandomGenerator & rng) const | ||||
| { | ||||
| 	object->info.clear(); | ||||
|  | ||||
| 	std::map<si32, si32> thrownDice; | ||||
|  | ||||
| 	configureRewards(object, rng, parameters["rewards"], thrownDice, CRewardVisitInfo::EVENT_FIRST_VISIT); | ||||
| 	configureRewards(object, rng, parameters["onVisited"], thrownDice, CRewardVisitInfo::EVENT_ALREADY_VISITED); | ||||
| 	configureRewards(object, rng, parameters["onEmpty"], thrownDice, CRewardVisitInfo::EVENT_NOT_AVAILABLE); | ||||
|  | ||||
| 	object->blockVisit= parameters["blockedVisitable"].Bool(); | ||||
| 	object->onSelect  = loadMessage(parameters["onSelectMessage"]); | ||||
| 	object->onVisited = loadMessage(parameters["onVisitedMessage"]); | ||||
| 	object->onEmpty   = loadMessage(parameters["onEmptyMessage"]); | ||||
| 	object->resetDuration = static_cast<ui16>(parameters["resetDuration"].Float()); | ||||
|  | ||||
| 	if (!parameters["onVisitedMessage"].isNull()) | ||||
| 	{ | ||||
| 		CRewardVisitInfo onVisited; | ||||
| 		onVisited.visitType = CRewardVisitInfo::EVENT_ALREADY_VISITED; | ||||
| 		onVisited.message = loadMessage(parameters["onVisitedMessage"]); | ||||
| 		object->info.push_back(onVisited); | ||||
| 	} | ||||
|  | ||||
| 	if (!parameters["onEmptyMessage"].isNull()) | ||||
| 	{ | ||||
| 		CRewardVisitInfo onEmpty; | ||||
| 		onEmpty.visitType = CRewardVisitInfo::EVENT_NOT_AVAILABLE; | ||||
| 		onEmpty.message = loadMessage(parameters["onEmptyMessage"]); | ||||
| 		object->info.push_back(onEmpty); | ||||
| 	} | ||||
|  | ||||
| 	configureResetInfo(object, rng, object->resetParameters, parameters["resetParameters"]); | ||||
|  | ||||
| 	object->canRefuse = parameters["canRefuse"].Bool(); | ||||
| 	 | ||||
| 	auto visitMode = parameters["visitMode"].String(); | ||||
|   | ||||
| @@ -19,6 +19,14 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
| class DLL_LINKAGE CRandomRewardObjectInfo : public IObjectInfo | ||||
| { | ||||
| 	JsonNode parameters; | ||||
|  | ||||
| 	void configureRewards(CRewardableObject * object, CRandomGenerator & rng, const JsonNode & source, std::map<si32, si32> & thrownDice, CRewardVisitInfo::ERewardEventType mode) const; | ||||
|  | ||||
| 	void configureLimiter(CRewardableObject * object, CRandomGenerator & rng, CRewardLimiter & limiter, const JsonNode & source) const; | ||||
| 	TRewardLimitersList configureSublimiters(CRewardableObject * object, CRandomGenerator & rng, const JsonNode & source) const; | ||||
|  | ||||
| 	void configureReward(CRewardableObject * object, CRandomGenerator & rng, CRewardInfo & info, const JsonNode & source) const; | ||||
| 	void configureResetInfo(CRewardableObject * object, CRandomGenerator & rng, CRewardResetInfo & info, const JsonNode & source) const; | ||||
| public: | ||||
| 	bool givesResources() const override; | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -19,20 +19,30 @@ VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| class CRandomRewardObjectInfo; | ||||
|  | ||||
| class CRewardLimiter; | ||||
| using TRewardLimitersList = std::vector<std::shared_ptr<CRewardLimiter>>; | ||||
|  | ||||
| /// Limiters of rewards. Rewards will be granted to hero only if he satisfies requirements | ||||
| /// Note: for this is only a test - it won't remove anything from hero (e.g. artifacts or creatures) | ||||
| /// NOTE: in future should (partially) replace seer hut/quest guard quests checks | ||||
| class DLL_LINKAGE CRewardLimiter | ||||
| { | ||||
| public: | ||||
| 	/// how many times this reward can be granted, 0 for unlimited | ||||
| 	si32 numOfGrants; | ||||
|  | ||||
| 	/// day of week, unused if 0, 1-7 will test for current day of week | ||||
| 	si32 dayOfWeek; | ||||
| 	si32 daysPassed; | ||||
|  | ||||
| 	/// total experience that hero needs to have | ||||
| 	si32 heroExperience; | ||||
|  | ||||
| 	/// level that hero needs to have | ||||
| 	si32 minLevel; | ||||
| 	si32 heroLevel; | ||||
|  | ||||
| 	/// mana points that hero needs to have | ||||
| 	si32 manaPoints; | ||||
|  | ||||
| 	/// percentage of mana points that hero needs to have | ||||
| 	si32 manaPercentage; | ||||
|  | ||||
| 	/// resources player needs to have in order to trigger reward | ||||
| 	TResources resources; | ||||
| @@ -45,13 +55,25 @@ public: | ||||
| 	/// Note: does not checks for multiple copies of the same arts | ||||
| 	std::vector<ArtifactID> artifacts; | ||||
|  | ||||
| 	/// Spells that hero must have in the spellbook | ||||
| 	std::vector<SpellID> spells; | ||||
|  | ||||
| 	/// creatures that hero needs to have | ||||
| 	std::vector<CStackBasicDescriptor> creatures; | ||||
|  | ||||
| 	/// sub-limiters, all must pass for this limiter to pass | ||||
| 	TRewardLimitersList allOf; | ||||
|  | ||||
| 	/// sub-limiters, at least one should pass for this limiter to pass | ||||
| 	TRewardLimitersList anyOf; | ||||
|  | ||||
| 	/// sub-limiters, none should pass for this limiter to pass | ||||
| 	TRewardLimitersList noneOf; | ||||
|  | ||||
| 	CRewardLimiter(): | ||||
| 		numOfGrants(0), | ||||
| 		dayOfWeek(0), | ||||
| 		minLevel(0), | ||||
| 		daysPassed(0), | ||||
| 		heroLevel(0), | ||||
| 		primary(4, 0) | ||||
| 	{} | ||||
|  | ||||
| @@ -59,14 +81,47 @@ public: | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & numOfGrants; | ||||
| 		h & dayOfWeek; | ||||
| 		h & minLevel; | ||||
| 		h & daysPassed; | ||||
| 		h & heroExperience; | ||||
| 		h & heroLevel; | ||||
| 		h & manaPoints; | ||||
| 		h & manaPercentage; | ||||
| 		h & resources; | ||||
| 		h & primary; | ||||
| 		h & secondary; | ||||
| 		h & artifacts; | ||||
| 		h & creatures; | ||||
| 		h & allOf; | ||||
| 		h & anyOf; | ||||
| 		h & noneOf; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CRewardResetInfo | ||||
| { | ||||
| public: | ||||
| 	CRewardResetInfo() | ||||
| 		: period(0) | ||||
| 		, visitors(false) | ||||
| 		, rewards(false) | ||||
| 	{} | ||||
|  | ||||
| 	/// if above zero, object state will be reset each resetDuration days | ||||
| 	ui32 period; | ||||
|  | ||||
| 	/// if true - reset list of visitors (heroes & players) on reset | ||||
| 	bool visitors; | ||||
|  | ||||
|  | ||||
| 	/// if true - re-randomize rewards on a new week | ||||
| 	bool rewards; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & period; | ||||
| 		h & visitors; | ||||
| 		h & rewards; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| @@ -79,12 +134,16 @@ public: | ||||
| 	TResources resources; | ||||
|  | ||||
| 	/// received experience | ||||
| 	ui32 gainedExp; | ||||
| 	si32 heroExperience; | ||||
| 	/// received levels (converted into XP during grant) | ||||
| 	ui32 gainedLevels; | ||||
| 	si32 heroLevel; | ||||
|  | ||||
| 	/// mana given to/taken from hero, fixed value | ||||
| 	si32 manaDiff; | ||||
|  | ||||
| 	/// if giving mana points puts hero above mana pool, any overflow will be multiplied by specified percentage | ||||
| 	si32 manaOverflowFactor; | ||||
|  | ||||
| 	/// fixed value, in form of percentage from max | ||||
| 	si32 manaPercentage; | ||||
|  | ||||
| @@ -100,6 +159,9 @@ public: | ||||
| 	std::vector<si32> primary; | ||||
| 	std::map<SecondarySkill, si32> secondary; | ||||
|  | ||||
| 	/// creatures that will be changed in hero's army | ||||
| 	std::map<CreatureID, CreatureID> creaturesChange; | ||||
|  | ||||
| 	/// objects that hero may receive | ||||
| 	std::vector<ArtifactID> artifacts; | ||||
| 	std::vector<SpellID> spells; | ||||
| @@ -117,8 +179,8 @@ public: | ||||
| 	Component getDisplayedComponent(const CGHeroInstance * h) const; | ||||
|  | ||||
| 	CRewardInfo() : | ||||
| 		gainedExp(0), | ||||
| 		gainedLevels(0), | ||||
| 		heroExperience(0), | ||||
| 		heroLevel(0), | ||||
| 		manaDiff(0), | ||||
| 		manaPercentage(-1), | ||||
| 		movePoints(0), | ||||
| @@ -134,9 +196,10 @@ public: | ||||
| 		h & removeObject; | ||||
| 		h & manaPercentage; | ||||
| 		h & movePercentage; | ||||
| 		h & gainedExp; | ||||
| 		h & gainedLevels; | ||||
| 		h & heroExperience; | ||||
| 		h & heroLevel; | ||||
| 		h & manaDiff; | ||||
| 		h & manaOverflowFactor; | ||||
| 		h & movePoints; | ||||
| 		h & primary; | ||||
| 		h & secondary; | ||||
| @@ -144,42 +207,44 @@ public: | ||||
| 		h & artifacts; | ||||
| 		h & spells; | ||||
| 		h & creatures; | ||||
| 		h & creaturesChange; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CVisitInfo | ||||
| class DLL_LINKAGE CRewardVisitInfo | ||||
| { | ||||
| public: | ||||
| 	enum ERewardEventType | ||||
| 	{ | ||||
| 		EVENT_INVALID, | ||||
| 		EVENT_FIRST_VISIT, | ||||
| 		EVENT_ALREADY_VISITED, | ||||
| 		EVENT_NOT_AVAILABLE | ||||
| 	}; | ||||
|  | ||||
| 	CRewardLimiter limiter; | ||||
| 	CRewardInfo reward; | ||||
|  | ||||
| 	/// Message that will be displayed on granting of this reward, if not empty | ||||
| 	MetaString message; | ||||
|  | ||||
| 	/// Chance for this reward to be selected in case of random choice | ||||
| 	si32 selectChance; | ||||
| 	/// Event to which this reward is assigned | ||||
| 	ERewardEventType visitType; | ||||
|  | ||||
| 	/// How many times this reward has been granted since last reset | ||||
| 	si32 numOfGrants; | ||||
|  | ||||
| 	CVisitInfo(): | ||||
| 		selectChance(0), | ||||
| 		numOfGrants(0) | ||||
| 	{} | ||||
| 	CRewardVisitInfo() = default; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & limiter; | ||||
| 		h & reward; | ||||
| 		h & message; | ||||
| 		h & selectChance; | ||||
| 		h & numOfGrants; | ||||
| 		h & visitType; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| namespace Rewardable | ||||
| { | ||||
| 	const std::array<std::string, 3> SelectModeString{"selectFirst", "selectPlayer", "selectRandom"}; | ||||
| 	const std::array<std::string, 3> SelectModeString{"selectFirst", "selectPlayer"}; | ||||
| 	const std::array<std::string, 5> VisitModeString{"unlimited", "once", "hero", "bonus", "player"}; | ||||
| } | ||||
|  | ||||
| @@ -188,20 +253,12 @@ namespace Rewardable | ||||
| class DLL_LINKAGE CRewardableObject : public CArmedInstance | ||||
| { | ||||
| 	/// function that must be called if hero got level-up during grantReward call | ||||
| 	void grantRewardAfterLevelup(const CVisitInfo & reward, const CGHeroInstance * hero) const; | ||||
| 	void grantRewardAfterLevelup(const CRewardVisitInfo & reward, const CGHeroInstance * hero) const; | ||||
|  | ||||
| 	/// grants reward to hero | ||||
| 	void grantRewardBeforeLevelup(const CVisitInfo & reward, const CGHeroInstance * hero) const; | ||||
|  | ||||
| protected: | ||||
| 	/// controls selection of reward granted to player | ||||
| 	enum ESelectMode | ||||
| 	{ | ||||
| 		SELECT_FIRST,  // first reward that matches limiters | ||||
| 		SELECT_PLAYER, // player can select from all allowed rewards | ||||
| 		SELECT_RANDOM  // reward will be selected from allowed randomly | ||||
| 	}; | ||||
| 	void grantRewardBeforeLevelup(const CRewardVisitInfo & reward, const CGHeroInstance * hero) const; | ||||
|  | ||||
| public: | ||||
| 	enum EVisitMode | ||||
| 	{ | ||||
| 		VISIT_UNLIMITED, // any number of times. Side effect - object hover text won't contain visited/not visited text | ||||
| @@ -211,37 +268,52 @@ protected: | ||||
| 		VISIT_PLAYER     // every player can visit object once | ||||
| 	}; | ||||
|  | ||||
| protected: | ||||
| 	/// controls selection of reward granted to player | ||||
| 	enum ESelectMode | ||||
| 	{ | ||||
| 		SELECT_FIRST,  // first reward that matches limiters | ||||
| 		SELECT_PLAYER, // player can select from all allowed rewards | ||||
| 	}; | ||||
|  | ||||
| 	/// filters list of visit info and returns rewards that can be granted to current hero | ||||
| 	virtual std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero) const; | ||||
| 	virtual std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero, CRewardVisitInfo::ERewardEventType event ) const; | ||||
|  | ||||
| 	virtual void grantReward(ui32 rewardID, const CGHeroInstance * hero) const; | ||||
| 	virtual void grantReward(ui32 rewardID, const CGHeroInstance * hero, bool markVisited) const; | ||||
|  | ||||
| 	virtual CVisitInfo getVisitInfo(int index, const CGHeroInstance *h) const; | ||||
| 	virtual void triggerReset() const; | ||||
|  | ||||
| 	virtual void triggerRewardReset() const; | ||||
|  | ||||
| 	/// Rewards that can be granted by an object | ||||
| 	std::vector<CVisitInfo> info; | ||||
|  | ||||
| 	/// MetaString's that contain text for messages for specific situations | ||||
| 	/// Message that will be shown if player needs to select one of multiple rewards | ||||
| 	MetaString onSelect; | ||||
| 	MetaString onVisited; | ||||
| 	MetaString onEmpty; | ||||
|  | ||||
| 	/// Rewards that can be applied by an object | ||||
| 	std::vector<CRewardVisitInfo> info; | ||||
|  | ||||
| 	/// how reward will be selected, uses ESelectMode enum | ||||
| 	ui8 selectMode; | ||||
|  | ||||
| 	/// contols who can visit an object, uses EVisitMode enum | ||||
| 	ui8 visitMode; | ||||
|  | ||||
| 	/// reward selected by player | ||||
| 	ui16 selectedReward; | ||||
|  | ||||
| 	/// object visitability info will be reset each resetDuration days | ||||
| 	ui16 resetDuration; | ||||
| 	/// how and when should the object be reset | ||||
| 	CRewardResetInfo resetParameters; | ||||
|  | ||||
| 	/// if true - player can refuse visiting an object (e.g. Tomb) | ||||
| 	bool canRefuse; | ||||
|  | ||||
| 	/// return true if this object was "cleared" before and no longer has rewards applicable to selected hero | ||||
| 	/// unlike wasVisited, this method uses information not available to player owner, for example, if object was cleared by another player before | ||||
| 	bool wasVisitedBefore(const CGHeroInstance * contextHero) const; | ||||
|  | ||||
| 	bool onceVisitableObjectCleared; | ||||
|  | ||||
| public: | ||||
| 	EVisitMode getVisitMode() const; | ||||
| 	ui16 getResetDuration() const; | ||||
|  | ||||
| 	void setPropertyDer(ui8 what, ui32 val) override; | ||||
| 	std::string getHoverText(PlayerColor player) const override; | ||||
| 	std::string getHoverText(const CGHeroInstance * hero) const override; | ||||
| @@ -262,9 +334,6 @@ public: | ||||
| 	/// applies player selection of reward | ||||
| 	void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; | ||||
|  | ||||
| 	/// function that will be called once reward is fully granted to hero | ||||
| 	virtual void onRewardGiven(const CGHeroInstance * hero) const; | ||||
| 	 | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CRewardableObject(); | ||||
| @@ -274,116 +343,18 @@ public: | ||||
| 		h & static_cast<CArmedInstance&>(*this); | ||||
| 		h & info; | ||||
| 		h & canRefuse; | ||||
| 		h & resetDuration; | ||||
| 		h & resetParameters; | ||||
| 		h & onSelect; | ||||
| 		h & onVisited; | ||||
| 		h & onEmpty; | ||||
| 		h & visitMode; | ||||
| 		h & selectMode; | ||||
| 		h & selectedReward; | ||||
| 		h & onceVisitableObjectCleared; | ||||
| 	} | ||||
|  | ||||
| 	// for configuration/object setup | ||||
| 	friend class CRandomRewardObjectInfo; | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGPickable : public CRewardableObject //campfire, treasure chest, Flotsam, Shipwreck Survivor, Sea Chest | ||||
| { | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CGPickable(); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CRewardableObject&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGBonusingObject : public CRewardableObject //objects giving bonuses to luck/morale/movement | ||||
| { | ||||
| protected: | ||||
| 	CVisitInfo getVisitInfo(int index, const CGHeroInstance *h) const override; | ||||
|  | ||||
| 	void grantReward(ui32 rewardID, const CGHeroInstance * hero) const override; | ||||
|  | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CGBonusingObject(); | ||||
|  | ||||
| 	void onHeroVisit(const CGHeroInstance *h) const override; | ||||
|  | ||||
| 	bool wasVisited(const CGHeroInstance * h) const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CRewardableObject&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGOnceVisitable : public CRewardableObject // wagon, corpse, lean to, warriors tomb | ||||
| { | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CGOnceVisitable(); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CRewardableObject&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGVisitableOPH : public CRewardableObject //objects visitable only once per hero | ||||
| { | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CGVisitableOPH(); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CRewardableObject&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGVisitableOPW : public CRewardableObject //objects visitable once per week | ||||
| { | ||||
| protected: | ||||
| 	void triggerRewardReset() const override; | ||||
|  | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
|  | ||||
| 	CGVisitableOPW(); | ||||
|  | ||||
| 	void setPropertyDer(ui8 what, ui32 val) override; | ||||
| 	void setRandomReward(CRandomGenerator & rand); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CRewardableObject&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| ///Special case - magic spring that has two separate visitable entrances | ||||
| class DLL_LINKAGE CGMagicSpring : public CGVisitableOPW | ||||
| { | ||||
| protected: | ||||
| 	std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero) const override; | ||||
|  | ||||
| public: | ||||
| 	void initObj(CRandomGenerator & rand) override; | ||||
| 	std::vector<int3> getVisitableOffsets() const; | ||||
| 	int3 getVisitableOffset() const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CGVisitableOPW&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| //TODO: | ||||
|  | ||||
| // MAX | ||||
|   | ||||
| @@ -32,15 +32,45 @@ namespace JsonRandom | ||||
| 		if (value.isNumber()) | ||||
| 			return static_cast<si32>(value.Float()); | ||||
| 		if (!value["amount"].isNull()) | ||||
| 			return static_cast<si32>(value["amount"].Float()); | ||||
| 			return static_cast<si32>(loadValue(value["amount"], rng, defaultValue)); | ||||
| 		si32 min = static_cast<si32>(value["min"].Float()); | ||||
| 		si32 max = static_cast<si32>(value["max"].Float()); | ||||
| 		return rng.getIntRange(min, max)(); | ||||
| 	} | ||||
|  | ||||
| 	DLL_LINKAGE std::string loadKey(const JsonNode & value, CRandomGenerator & rng, std::string defaultValue) | ||||
| 	{ | ||||
| 		if (value.isNull()) | ||||
| 			return defaultValue; | ||||
| 		if (value.isString()) | ||||
| 			return value.String(); | ||||
| 		if (!value["type"].isNull()) | ||||
| 			return value["type"].String(); | ||||
|  | ||||
| 		if (value["list"].isNull()) | ||||
| 			return defaultValue; | ||||
|  | ||||
| 		const auto & resourceList = value["list"].Vector(); | ||||
|  | ||||
| 		if (resourceList.empty()) | ||||
| 			return defaultValue; | ||||
|  | ||||
| 		si32 index = rng.getIntRange(0, resourceList.size() - 1 )(); | ||||
|  | ||||
| 		return resourceList[index].String(); | ||||
| 	} | ||||
|  | ||||
| 	TResources loadResources(const JsonNode & value, CRandomGenerator & rng) | ||||
| 	{ | ||||
| 		TResources ret; | ||||
|  | ||||
| 		if (value.isVector()) | ||||
| 		{ | ||||
| 			for (const auto & entry : value.Vector()) | ||||
| 				ret += loadResource(entry, rng); | ||||
| 			return ret; | ||||
| 		} | ||||
|  | ||||
| 		for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++) | ||||
| 		{ | ||||
| 			ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng); | ||||
| @@ -48,6 +78,18 @@ namespace JsonRandom | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
| 	TResources loadResource(const JsonNode & value, CRandomGenerator & rng) | ||||
| 	{ | ||||
| 		std::string resourceName = loadKey(value, rng, ""); | ||||
| 		si32 resourceAmount = loadValue(value, rng, 0); | ||||
| 		si32 resourceID(VLC->modh->identifiers.getIdentifier(value.meta, "resource", resourceName).get()); | ||||
|  | ||||
| 		TResources ret; | ||||
| 		ret[resourceID] = resourceAmount; | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng) | ||||
| 	{ | ||||
| 		std::vector<si32> ret; | ||||
| @@ -131,8 +173,6 @@ namespace JsonRandom | ||||
| 	{ | ||||
| 		if (value.getType() == JsonNode::JsonType::DATA_STRING) | ||||
| 			return SpellID(VLC->modh->identifiers.getIdentifier("spell", value).get()); | ||||
| 		if (value["type"].getType() == JsonNode::JsonType::DATA_STRING) | ||||
| 			return SpellID(VLC->modh->identifiers.getIdentifier("spell", value["type"]).get()); | ||||
|  | ||||
| 		vstd::erase_if(spells, [=](SpellID spell) | ||||
| 		{ | ||||
|   | ||||
| @@ -32,7 +32,9 @@ namespace JsonRandom | ||||
| 	}; | ||||
|  | ||||
| 	DLL_LINKAGE si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0); | ||||
| 	DLL_LINKAGE std::string loadKey(const JsonNode & value, CRandomGenerator & rng, std::string defaultValue = ""); | ||||
| 	DLL_LINKAGE TResources loadResources(const JsonNode & value, CRandomGenerator & rng); | ||||
| 	DLL_LINKAGE TResources loadResource(const JsonNode & value, CRandomGenerator & rng); | ||||
| 	DLL_LINKAGE std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng); | ||||
| 	DLL_LINKAGE std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng); | ||||
|  | ||||
|   | ||||
| @@ -1523,32 +1523,6 @@ void CGWitchHut::serializeJsonOptions(JsonSerializeFormat & handler) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGMagicWell::onHeroVisit( const CGHeroInstance * h ) const | ||||
| { | ||||
| 	int message; | ||||
|  | ||||
| 	if(h->hasBonusFrom(Bonus::OBJECT,ID)) //has already visited Well today | ||||
| 	{ | ||||
| 		message = 78;//"A second drink at the well in one day will not help you." | ||||
| 	} | ||||
| 	else if(h->mana < h->manaLimit()) | ||||
| 	{ | ||||
| 		giveDummyBonus(h->id); | ||||
| 		cb->setManaPoints(h->id,h->manaLimit()); | ||||
| 		message = 77; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		message = 79; | ||||
| 	} | ||||
| 	showInfoDialog(h, message); | ||||
| } | ||||
|  | ||||
| std::string CGMagicWell::getHoverText(const CGHeroInstance * hero) const | ||||
| { | ||||
| 	return getObjectName() + " " + visitedTxt(hero->hasBonusFrom(Bonus::OBJECT,ID)); | ||||
| } | ||||
|  | ||||
| void CGObservatory::onHeroVisit( const CGHeroInstance * h ) const | ||||
| { | ||||
| 	InfoWindow iw; | ||||
|   | ||||
| @@ -391,18 +391,6 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGMagicWell : public CGObjectInstance //objects giving bonuses to luck/morale/movement | ||||
| { | ||||
| public: | ||||
| 	void onHeroVisit(const CGHeroInstance * h) const override; | ||||
| 	std::string getHoverText(const CGHeroInstance * hero) const override; | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<CGObjectInstance&>(*this); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_LINKAGE CGSirens : public CGObjectInstance | ||||
| { | ||||
| public: | ||||
|   | ||||
| @@ -45,7 +45,6 @@ void registerTypesMapObjects1(Serializer &s) | ||||
| 			s.template registerType<CGMonolith, CGWhirlpool>(); | ||||
| 	s.template registerType<CGObjectInstance, CGSignBottle>(); | ||||
| 	s.template registerType<CGObjectInstance, CGScholar>(); | ||||
| 	s.template registerType<CGObjectInstance, CGMagicWell>(); | ||||
| 	s.template registerType<CGObjectInstance, CGObservatory>(); | ||||
| 	s.template registerType<CGObjectInstance, CGKeys>(); | ||||
| 		s.template registerType<CGKeys, CGKeymasterTent>(); | ||||
| @@ -99,7 +98,6 @@ void registerTypesMapObjectTypes(Serializer &s) | ||||
| 	REGISTER_GENERIC_HANDLER(CGArtifact); | ||||
| 	REGISTER_GENERIC_HANDLER(CGBlackMarket); | ||||
| 	REGISTER_GENERIC_HANDLER(CGBoat); | ||||
| 	REGISTER_GENERIC_HANDLER(CGBonusingObject); | ||||
| 	REGISTER_GENERIC_HANDLER(CGBorderGate); | ||||
| 	REGISTER_GENERIC_HANDLER(CGBorderGuard); | ||||
| 	REGISTER_GENERIC_HANDLER(CGCreature); | ||||
| @@ -113,15 +111,11 @@ void registerTypesMapObjectTypes(Serializer &s) | ||||
| 	REGISTER_GENERIC_HANDLER(CGLighthouse); | ||||
| 	REGISTER_GENERIC_HANDLER(CGTerrainPatch); | ||||
| 	REGISTER_GENERIC_HANDLER(CGMagi); | ||||
| 	REGISTER_GENERIC_HANDLER(CGMagicSpring); | ||||
| 	REGISTER_GENERIC_HANDLER(CGMagicWell); | ||||
| 	REGISTER_GENERIC_HANDLER(CGMarket); | ||||
| 	REGISTER_GENERIC_HANDLER(CGMine); | ||||
| 	REGISTER_GENERIC_HANDLER(CGObelisk); | ||||
| 	REGISTER_GENERIC_HANDLER(CGObservatory); | ||||
| 	REGISTER_GENERIC_HANDLER(CGOnceVisitable); | ||||
| 	REGISTER_GENERIC_HANDLER(CGPandoraBox); | ||||
| 	REGISTER_GENERIC_HANDLER(CGPickable); | ||||
| 	REGISTER_GENERIC_HANDLER(CGQuestGuard); | ||||
| 	REGISTER_GENERIC_HANDLER(CGResource); | ||||
| 	REGISTER_GENERIC_HANDLER(CGScholar); | ||||
| @@ -135,8 +129,6 @@ void registerTypesMapObjectTypes(Serializer &s) | ||||
| 	REGISTER_GENERIC_HANDLER(CGWhirlpool); | ||||
| 	REGISTER_GENERIC_HANDLER(CGTownInstance); | ||||
| 	REGISTER_GENERIC_HANDLER(CGUniversity); | ||||
| 	REGISTER_GENERIC_HANDLER(CGVisitableOPH); | ||||
| 	REGISTER_GENERIC_HANDLER(CGVisitableOPW); | ||||
| 	REGISTER_GENERIC_HANDLER(CGWitchHut); | ||||
|  | ||||
| #undef REGISTER_GENERIC_HANDLER | ||||
| @@ -162,12 +154,6 @@ void registerTypesMapObjects2(Serializer &s) | ||||
| 			s.template registerType<CGTownBuilding, COPWBonus>(); | ||||
|  | ||||
| 	s.template registerType<CGObjectInstance, CRewardableObject>(); | ||||
| 		s.template registerType<CRewardableObject, CGPickable>(); | ||||
| 		s.template registerType<CRewardableObject, CGBonusingObject>(); | ||||
| 		s.template registerType<CRewardableObject, CGVisitableOPH>(); | ||||
| 		s.template registerType<CRewardableObject, CGVisitableOPW>(); | ||||
| 		s.template registerType<CRewardableObject, CGOnceVisitable>(); | ||||
| 			s.template registerType<CGVisitableOPW, CGMagicSpring>(); | ||||
|  | ||||
| 	s.template registerType<CGObjectInstance, CTeamVisited>(); | ||||
| 		s.template registerType<CTeamVisited, CGWitchHut>(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user