В файле CvEnums.h новые значения надо добавлять в конец списка перед значением обозначающим количество всех значений, название которого начинается на NUM_. В твоем случае WIDGET_HELP_WAREHOUSE надо добавлять после WIDGET_GOTO_CITY перед NUM_WIDGET_TYPES.
Все дело в том что при кампиляции названия энумом заменяются на обычные числа начиная с нуля или того числа которое указано в самом первом энуме, причем число следующего энума на 1 больше предыдущего. Так вот, весь прикол в том что экзешник скомпилирован с теми значениями энумов которые установлены в оригинальном CvEnums.h, если ты добавляешь новый энум в середину списка, то все энумы после него становатся больше на 1. Но они становятся больше только в твоем DLL и питоне, а в экзешнике остаются старыми. В итоге при нажатии кнопки через пион передается число на 1 больше того что предусмотрено в экзешнике. Ну и естественно экзешник питается выполнить алгоритм, который не предусмотрен для выполнения с данными которые передаются при нажатии кнопки.
В подсказку можно добавить прибавление ресурсов
В подсказку TXT_KEY_MISC_WAREHOUSE надо добавить новую строчку отображающую прибавление или убавление ресурсов. Как в подсказке про очки рождаимости.Код:void CvDLLWidgetData::parseWarehouseHelp(CvWidgetDataStruct &widgetDataStruct, CvWStringBuffer &szBuffer) { if (GC.getNEW_CAPACITY() != 0) { CvCity* pHeadSelectedCity = gDLL->getInterfaceIFace()->getHeadSelectedCity(); if (pHeadSelectedCity != NULL) { int iI, iJ, iNumProfessionInfos, iUnproducedYield, iYieldConsumed, iProducedYield; int aiProducedYields[NUM_YIELD_TYPES]; bool bBIRTH_POINTS = (GC.getBASE_BIRTH_POINTS_THRESHOLD() != 0); iNumProfessionInfos = GC.getNumProfessionInfos(); for (iI = 0; iI < NUM_YIELD_TYPES; iI++) {aiProducedYields[iI] = 0;} for (iI = 0; iI < NUM_YIELD_TYPES; iI++) { iUnproducedYield = pHeadSelectedCity->calculateActualYieldProduced((YieldTypes)iI) - pHeadSelectedCity->getBaseRawYieldProduced((YieldTypes)iI); if (iUnproducedYield < 0) { for (iJ = 0; iJ < iNumProfessionInfos; iJ++) { CvProfessionInfo& kProfession = GC.getProfessionInfo((ProfessionTypes)iJ); if (kProfession.getYieldProduced() == iI) { iYieldConsumed = kProfession.getYieldConsumed(); if (iYieldConsumed != NO_YIELD) {aiProducedYields[iYieldConsumed] += iUnproducedYield;} } } } aiProducedYields[iI] += pHeadSelectedCity->calculateNetYield((YieldTypes)iI); } iProducedYield = 0; for (iI = 0; iI < NUM_YIELD_TYPES; iI++) { if ((bBIRTH_POINTS || (iI != YIELD_FOOD)) && GC.getYieldInfo((YieldTypes)iI).isCargo()) {iProducedYield += aiProducedYields[iI];} } szBuffer.assign(gDLL->getText("TXT_KEY_MISC_WAREHOUSE", pHeadSelectedCity->getTotalYieldStored(), iProducedYield, pHeadSelectedCity->getMaxYieldCapacity())); } } }
В процессе тестирования выявил и исправил пару небольших багов, а также сделал некоторые корректировки параметров.
1. При рождении нового поселенца значения BirthPoints на экране города становились отрицательными. Через пару ходов все устаканивалось, но такого быть не может, так как значения BirthPoints не могут быть отрицательными по определению, ибо они привязаны к количеству потребляемой поселенцем еды.
Это происходило из-за того, что в CvCity.cpp на момент перехода расчет велся так:
а должно было быть так:Код:setBirthPoints(iGrowthThreshold - iBirthPoints);
В таком виде все работает правильно.Код:setBirthPoints(iBirthPoints - iGrowthThreshold);
2. Второй баг, уже в CvMainInterface.py, я создал сам, когда убрал в подсказку количество товаров на складе и его максимальную вместимость и оставил на экране только прирост наполняемости склада за ход (iProdusedYield).
Все работало нормально до того момента, пока значения были iProdusedYield > 0 или iProdusedYield < 0. Но в ситуации, когда iProdusedYield = 0, значок склада с экрана просто исчезал. Для исправления этого я добавил в CvMainInterface.py строку с "else"
Так все работает правильно.Код:if iProdusedYield > 0: szBuffer += u"+" + u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" elif iProdusedYield < 0: szBuffer += u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" else: szBuffer += u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" #KJ addon if "iProdusedYield = 0"
"BAD_GOLD_CHAR" пусть не смущает, так как в GameFont.tga значок склада я поместил вместо значка BAD_GOLD_CHAR, который в игре нигде не используется.
3. Удлинил до 10 ходов предупреждение о скором переполнении городского склада. Теперь в CvMainInterface.py это выглядит так:
Как и было сделано VET'ом в оригинале, цифры перед значком склада меняют цвет с зеленого на желтый, но желтыми они становятся за 10, а не за 2 хода до возможного переполнения склада. Из-за обилия информации я частенько упускал этот момент и склад оказывался набит до предела.Код:elif iTotalYield + (10 * iProdusedYield) > iMaxYield: #"10 turns's alarm before Max Storage capacity" szBuffer += u"255,255,0" #yellow
Теперь несколько замечаний по вновь введенным параметрам.
4. Неприкосновенный запас продовольствия, задаваемый через
При скорости игры 1 ход = 1 месяц мы имеем годовой запас продуктов питания. Очень разумно. Если память мне не изменяет, то в СССР был 90 дневный неприкосновенный запас продовольствия. Тут же годовой. Так что мы имеем вполне соизмеримые величины.Код:<DefineName>TURNS_FOR_FOOD</DefineName> <iDefineIntVal>12</iDefineIntVal>
5. Как показывает практика городской склад (BUILDING_WAREHOUSE) не является тем зданием, которое строится самым первым. Ни игрок, ни тем более AI, не начинают стоить склад сразу.
Это означает, что при нормальной скорости игры на самом первом ходу в городе может храниться только 100 единиц товара. Честно сказать, я не знаю откуда идет эта цифра, ведь склада в городе на самом первом ходу пока нет, а BUILDING_TOWNHALL, который есть по дефолту, имеет
Другие доступные по дефолту здания тоже. Возможно эта сотня где-то прописана в исходных кодах, но, признаюсь, я специально не искал. Это не важно, просто примем эту сотню как данность. Итак, на самом первом ходу в городе может храниться не более 100 единиц товара.Код:<iYieldStorage>0</iYieldStorage>
А теперь представим ситуацию, когда город основан юнитом, имеющим профессию "Драгун" (PROFESSION_DRAGOON). Согласно CIV4ProfessionInfos.xml в экипировку этого юнита входят:
То есть уже в момент основания все доступные в городе 100 единиц будут сразу же заполнены. Любой товар, что будет производиться в городе или собираться на клетках вокруг него, моментально будет подпадать под возможные сокращения.Код:<YieldEquipedNums> <YieldEquipedNum> <YieldType>YIELD_HORSES</YieldType> <iYieldAmount>50</iYieldAmount> </YieldEquipedNum> <YieldEquipedNum> <YieldType>YIELD_MUSKETS</YieldType> <iYieldAmount>50</iYieldAmount> </YieldEquipedNum> </YieldEquipedNums>
Для исправления этой ситуациидля в BUILDING_WAREHOUSE я ввел
Таким образом, сейчас при нормальной скорости получается суммарная вместимость города (без еще не построенного склада!) равна 100 + 100 = 200, то есть в 2 раза больше прежней. В этом случае даже при создании города драгуном не происходит моментального переполения еще не построенного "склада".Код:<iYieldStorage>100</iYieldStorage>
Соответственно в сторону повышения скорректированы и значения для BUILDING_WAREHOUSE
вместоКод:<iYieldStorage>900</iYieldStorage>
и для расширенного склада (BUILDING_WAREHOUSE_EXPANSION), где сейчасКод:<iYieldStorage>100</iYieldStorage>
вместоКод:<iYieldStorage>1500</iYieldStorage>
Эти изменения абсолютно необходимы, так как сейчас заполненность склада считается как сумма всех товаров, что хранятся в городе, а не отдельно по каждой из позиций, как это было в оригинальной игре.Код:<iYieldStorage>200</iYieldStorage>
6. Максимальное значение BirthPoints, при котором рождается новый колонист. В самом начале это значение было равно 200:
Но насколько оно оптимально?Код:<DefineName>BASE_BIRTH_POINTS_THRESHOLD</DefineName> <iDefineIntVal>200</iDefineIntVal>
Для ответа на этот вопрос надо совершить небольшой экскурс в историю и демографию.
Как известно, рост населения в любом городе определяется четырьмя слагаемыми.
- рождаемость,
- смертность,
- иммиграция (в город)
- эмиграция (из города).
Таким образом,
В первых скобках - естественный прирост населения, во вторых - искусственный (или механический).Прирост населения = (Рождаемость - Смертность) + (Иммиграция - Эмиграция).
В данном моде мы не разделяем по отдельности "Рождаемость" и "Смертность". Введенный параметер "BirthPoints" нужно рассматривать как естественный прирост населения, то есть как (Рождаемость - Смертность).
Безусловно, оба эти значения можно развести и параллельно с "BirthPoints" ввести "DeathPoints". Но тогда в какой-то момент, когда набирается некое количество "DeathPoints", нужно убивать одного из жителей города. Причем в обязательном порядке! Это неприятно и вряд ли будет приемлемо играющими, так как сейчас все юниты практически бессмертны. По крайней мере до тех пор, пока не началась война с туземцами или соседями-европейцами.
Поэтому "Смертность" проще ввести через генерацию случайных событий. К примеру, в густонаселенном городе (более 8 или 10 жителей) с вероятностью Х% вспыхивает эпидемия. Если в городе нет доступа к чистой воде (родник), или нет госпиталя, или лекарств, то тогда с очень высокой вероятностью один из жителей умирает. Если все вышеперечисленное есть, то город в период эпидемии ничего не производит и все заканчивается без потерь для игрока.
Мне кажется, что такое решение намного проще, чем введение параметра DeathPoints. Вероятностное событие может произойти, а может и не произойти. Тут все зависит от самого игрока.
Итак, мы имеем два компонента, ответственных за прирост населения города - естественный и искусственный.
Если изучить динамику роста городов в Новом Свете в период колонизации, то станет совершенно очевидно, что в первые как минимум 100 лет преобладающим механизмом был "искусственный" рост населения за счет:
- иммигрантов из Европы (в самом начале игры мы их постоянно возим из Европы),
- рабов из Африки (в данном моде отсутствуют, но они уже есть в "1492: Slavery Market. The Orient. Port-Royal"),
- захваченных или присоединившихся к европейцам местных аборигенов (в нашем случае, это UNIT_CONVERTED_NATIVE).
Кстати, массовый завоз рабов из Африки как раз и был связан с отсутствием необходимой рабочей силы во вновь основанных городах и в особенности на плантациях Нового Света.
То есть другими словами, параметр BASE_BIRTH_POINTS_THRESHOLD мы должны задать таким, чтобы в течение очень длительного периода времени население города не могло увеличиваться. Если оставить его равным 200, то новый житель в нем появится через 100 ходов. Считаем 1 ход = 1 месяц, получаем 100 месяцев или 100 : 12 = чуть больше 8 лет. Лично мне кажется, что это очень быстро.
Безусловно, увеличив BASE_BIRTH_POINTS_THRESHOLD до 300 или даже 500, мы получим более приемлемые значения. По крайней мере более правильные с исторической точки зрения. Поэтому моя рекомендация - использовать параметр BASE_BIRTH_POINTS_THRESHOLD с очень большим значением. Впрочем, это дело вкуса каждого из игроков и любой вправе поменять его сам. Параметр BASE_BIRTH_POINTS_THRESHOLD выведен в GlobalDefinesAlt.xml и его очень просто отредактировать.
Других изменений, за исключением незаконченного пока редактирования текстовых файлов, я не делал. Сейчас я правлю статьи с CONCEPT_FOOD, CONCEPT_NEW_STORAGE и CONCEPT_POPULATION_GROWTH.
Если мне ничего не помешает, то к концу этой недели мод "BirthPoints_and_NewCapacity" будет готов для публикации и представления игрокам.
Предлагаю его переименовать и назвать к примеру "New Colonists" ("Новые колонисты"). При этом в описании указать, что в данном моде изменена логика генерации новых поселенцев. Новый колонист (см. предлагаемый вариант названия мода) появляется не в результате накопления еды, а как следствия набора "очков рождаемости" всеми жителями данного города. Плюс естественно описать радикальные изменения, произведенные с городским складом.
Если новое название приемлемо, то тогда заставка твоего мода может выглядеть например так:
Да, и последнее. При довольно продолжительном тестовом прогоне я открыл карту и видел, что и как делают мои европейские оппоненты и местные аборигены. Сразу же хочу сказать, что их поведение меня порадовало. Никто из них тупо не гнался за увеличением запасов еды. Все были заняты сбором или производством чего-то своего, имея при этом гарантированный запас продовольствия, который обеспечивал постоянный набор "очков рождаемости". И самое главное, это происходило независимо от того, что они делали в городе или на клетках вокруг города. Города росли не быстро, первоначально их рост происходил за счет прибытия новых колонистов из Европы, затем же они стали сами источниками новых поселенцев, которые постепенно расселялись по карте. Лично мне такое поведение очень даже понравилось.
Базовый размер склада задается параметром CITY_YIELD_CAPACITY.
код
лучше заменить наКод:if iProdusedYield > 0: szBuffer += u"+" + u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" elif iProdusedYield < 0: szBuffer += u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" else: szBuffer += u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>" #KJ addon if "iProdusedYield = 0"
результат бутет точно таким, а размер кода гораздо меньшимКод:if iProdusedYield > 0: szBuffer += u"+" szBuffer += u"%i%c" % (iProdusedYield, CyGame().getSymbolID(FontSymbols.BAD_GOLD_CHAR)) + u"</font>"
Новые иконки можно добавить в файлах CvEnum.h (enum DllExport FontSymbols) через файл CyEnumsInterface.cpp.
Ага, теперь вижу откуда эта сотня берется. Очень ценное наблюдение, спасибо!
При переходе на новый принцип расчета загруженности городского склада и из-за возникающих при этом проблем (что я описал выше на примере "Драгуна"), куда правильнее просто увеличить в пару раз параметр CITY_YIELD_CAPACITY, а не извращаться вводя iYieldStorage для BUILDING_TOWNHALL.
Кроме того при таком решении автоматически увеличивается CITY_YIELD_CAPACITY не только для европейцев, но и для аборигенов, что важно при торговле с ними. Введение же дополнительного iYieldStorage для BUILDING_TOWNHALL такого не позволяло делать, поскольку аборигены не могут строить BUILDING_TOWNHALL.
Все верно, но это уже оптимизация программного кода, которой я никогда не занимался из-за отсутствия опыта.
В предложенном тобой варианте все работает, как и раньше. Насколько быстрее сказать не могу, но явно должно быть некое ускорение, раз этот участок кода в 3 раза короче.
Да, я знаю, но тут проблема не в добавлении новых иконок в CvEnum.h и CyEnumsInterface.cpp. Это работа займет не больше минуты, так как они встречаются в исходных кодах лишь в двух местах:
Основная проблема возникает в GameFont.tga со строкой, где должны быть расположены новые иконки. Она уже заполнена полностью. Я имею ввиду естественно оригинальный размер GameFont.tga, равный 640х320. В моде "1492: Глобальная Колонизация" я использую в 3 раза более длинный GameFont.tga с размером 1920х320.Код:CvGameCoreDLL\CvEnums.h (1 hits) Line 829: BAD_GOLD_CHAR, CvGameCoreDLL\CyEnumsInterface.cpp (2 hits) Line 508: .value("BAD_GOLD_CHAR", BAD_GOLD_CHAR) Line 508: .value("BAD_GOLD_CHAR", BAD_GOLD_CHAR)
Безусловно можно использовать такой же размер GameFont.tga файла и для данного мода, вот только надо ли это делать? Ведь часть иконок, типа BAD_GOLD_CHAR или GREAT_PEOPLE_CHAR, нигде в игре не используются. Это настоящие пустышки, оставшие от Цивилизации 4. Их я собственно и использовал даже без переименования в CvEnum.h и CyEnumsInterface.cpp, что кстати тоже можно было сделать совершенно безболезненно. В конце концов для обычного игрока без разницы, что там внутри кодов, а для профессионального мододела и так все ясно.
В моде "1492: Глобальная Колонизация" мне в обязательном порядке придется вносить изменения в порядок иконок в CvEnum.h и CyEnumsInterface.cpp, поскольку кроме BIRTHPOINTS_CHAR и WAREHOUSE_CHAR там возможно будут добавлен ряд новых иконок. Но все это будет делаться уже в "длинном" (1920х320) GameFont.tga файле.
Автор:
NeseryozniyVET - программирование (С++, Python)
при участии kabjans (KJ Jansson) - идея, тестирование, графика.
Рабочее название мода: "BirthPoints_and_NewCapacity"
Ссылка на скачивание: http://rghost.net/40609102
"New Colonists" ("Новые колонисты") версия 1.1: http://rghost.net/40682579
В данном моде кардинально изменена логика
- генерации новых поселенцев не как результат накопления еды, а как следствия набора "очков рождаемости" всеми жителями данного города,
- полностью изменен порядок расчета вместимости "городского склада".
Генерация новых поселенцев.
В оригинальной версии Колонизации новый житель города появляется при накопления в городе достаточного количества еды. Данное решение разработчиков игры выглядит мягко говоря довольно странным, поскольку от переедания дети, как известно, не рождаются. Тем не менее до сих пор было именно так.
Мод "Новые колонисты" кардинально изменяет условия появления нового жителя в городе. Каждый колонист, находящийся в городе (будь то работающий в городском здании или на клетке около города), не только потребляет определенное количество еды за ход, но одновременно генерит так называемые "очки рождаемости" (BirthPoints). Сумма этих очков, сгенерированных всеми жителями города, есть скорость прироста (Change per turn) BirthPoints для данного города.
Вся информация по "очкам рождаемости" выведена в верхнюю часть городского экрана рядом с названием города и его населением. Цифра показывает уже набранное количество BirthPoints. Наведя стрелку мыши на эту цифру или на расположенный рядом значок, можно получить всю информацию по "очкам рождаемости".
При наборе городом некого критического количества "очков рождаемости" (Threshold) в нем появляется новый житель.
Скорость генерации новых поселенцев.
Рост населения в любом городе определяется четырьмя слагаемыми.
- рождаемость,
- смертность,
- иммиграция (в город)
- эмиграция (из города),
которые можно описать простейшей формулой,
В первых скобках - естественный прирост населения, во вторых - искусственный (или механический).Прирост населения = (Рождаемость - Смертность) + (Иммиграция - Эмиграция).
"Очки рождаемости" (BirthPoints) следует рассматривать как естественный прирост населения, то есть как (Рождаемость - Смертность).
На начальных этапах игры преобладающим механизмом является "искусственный" (или механический) рост населения за счет прибытия новых иммигрантов из Европы, а также захваченных или присоединившихся к европейцам местных аборигенов (UNIT_CONVERTED_NATIVE).
В данной версии мода параметры подобраны таким образом, чтобы в городе, котором проживает 1 житель (на самом деле их 100, но в игре они отображаются как 1 житель), при игре на марафоне (GAMESPEED_MARATHON) и при условии 1 ход = 1 месяц, новый родившийся житель появлялся только через 50 лет.
Это сделано не только для того, чтобы придать определенную историческую достоверность скорости роста городов в Новом Свете в период колонизации, но и для поддержания относительного баланса на поздних стадиях игры. В итоге малонаселенный город генерит новых жителей очень медленно, а густонаселенный - не генерит их через несколько ходов. Все это описано в СивПедии в разделе "Концепции", см. "Population Growth".
Впрочем, желающие могут поэкспериментировать с параметрами сами, выбрав желаемые для них скорость и пороги рождения новых жителей.
Значение еды при новой системе генерации жителей.
Как и в реальной жизни, еда остается важнейшим условием существования города. Первоначально игроку необходимо запастись хотя бы минимальным количеством еды, гарантирующим отсуствие голода в городе. Если это условие выполнено, то жители начинают генерить "очки рождаемости". Если в городе голод - то жители покидают город и появляются на глобальной карте, как это и было в оригинальной игре. При нехватке еды или невозможности ее производить продовольствие можно завести из другого своего города, Европы или же купить у аборигенов. Все это описано в в СивПедии в разделе "Концепции", см. "Food".
Обратите внимание на появление нового понятия - "Неприкосновенный запас" ("Emergence Food Reserve"). Он рассчитывается как количество еды, которое необходимо всем жителям данного города при условии, что в город в течение 12 ходов не поступает или не производится его жителями никакое продовольствие. Понятие "Неприкосновенный запас" используется при работе городского склада в новых условия.
Расчет вместимости "городского склада".
В оригинальной версии Колонизации для каждого товара, хранящегося на городском складе, был выделен свой размер хранения. К примеру, при нормальной скорости на складе можно было хранить только 100 единиц руды. Если руды оказывалось больше, то избыток просто исчезал. При этом очень часто можно было наблюдать картину, когда все остальные ячейки склада, за исключением той, что относилась к еде, были совершенно пусты. Другими словами склад был практически пустой, но хранить производимый или добываемый в данном городе товар, в нем было невозможно. Любое превышение верхнего предела по данной позиции означало немедленную потерю данного товара.
Для еды правда было сделано исключение, поскольку при переполнении ячейки "Продовольствие" еда не исчезала, а появлялся новый колонист. При желании этот процесс можно было ускорить, свозя продовольствие из соседних городов или массово закупая его у аборигенов. Основная проблема была в том, что этот трюк был прекрасно известен игроку, но не AI, который управляет поведением остальных участников игры.
В данном моде расчет вместимости городского склада ведется намного более правильно и логично. Любой товар, включая еду, который имеется в наличии, добывается, собирается или производится в данном городе, хранится на городском складе. Сумма всех хранимых на складе в данный момент товаров - Stored goods (заполненность склада), прирост за ход - Change per turn, а Maх Capacity - максимальное количество товаров, которое может храниться на городском складе.
Вся информация о состоянии склада выведена в верхнюю часть городского экрана. Цифры, изображающие прирост хранимых товаров за ход могут быть со знаком "плюс" (склад пополняется) или "минус" (склад опорожняется). Обычно они зеленого цвета, однако за 10 ходов до возможного переполнения склада они меняют цвет и становятся желтыми. Когда же склад переполнен - эти цифры становятся красными. Очень рекомендуется в процессе игры следить за этими данными, вовремя вывозить (продавать) готовые товары или при необходимости строить расширенный склад.
Таким образом, в данном моде возможно избежать ситуации, описанной выше на примере руды. Максимальный размер хранимых товаров одного вида ограничен только вместимостью склада.
Переполнение "городского склада".
Во избежании быстрого переполнения склада в данном моде в 3 раза увеличен параметер CITY_YIELD_CAPACITY (GlobalDefines.xml). Это позволяет избегать потери товаров в начальной стадии игры, когда настоящий городской склад еще не построен, а город основан юнитом, имеющим вооружение и лошадей (к примеру, драгуном).
Однако в любой игре может наступить момент, когда склад, даже расширенный, все же будет переполнен. В этом случае действует простой принцип: "С переполненного склада исчезает самый дешевый товар". Поскольку продовольствие является одним из самых дешевых товаров, то оно также может исчезнуть. Однако в отличие от других дешевых товаров типа древесины или руды, потеря продовольствие идет не до нуля, а до размера "Неприкосновенного запаса". В этос случае сначала теряется еда, превышающая НЗ, затем следующий самый дешевый товар. Возможен иной вариант, когда город густонаселен, склад уже переполнен, а "Неприкосновенный запас" еще полностью не созданю В этом случае с переполненного склада будет исчезать не продовольствие, другие самые дешевые товары, даже если их стоимость в разы выше стоимости продовольствия.
Все это описано в СивПедии в разделе "Концепции", см. "City Storage" .
![]()
Я сделал несколько изменений
1) Немного подправил алгоритм в CvCity::doYields() после строчки //VET NewCapacity - begin 8/9
2) Сделал новую функцию CvCity::calculateTotalProducedYields() и заменил ею алгоритмы в CvDLLWidgetData.cpp и CvMainInterface.py
http://vet.civfanatics.ru/EoW/ColonistsPach.rar
P.S. для редактирования фалов (*.XML, *.py, *.cpp, *.h) лучше пользоваться Notepad++ (http://notepad-plus-plus.org/download/v6.1.8.html)
Спасибо, патч скачал, но скомпилировать и посмотреть изменения смогу только на выходных, когда буду у компьютера с игрой.
Я сам использую для редактирования всех файлов только Notepad++, а обычный текстовой редактор Notepad назвал для тех, у кого есть просто винда, игра и желание поэкспериментировать с данными. Для простейших изменений, к примеру цифр, его вполне достаточно. Для более серьезных вещей безусловно лучше использовать Notepad++ или его аналоги.
Привет, NeseryozniyVET!
Патч, оптимизирующий вывод данных на экран, мне удалось-таки совместить с текущей версией мода. При первой компиляции я получил букет ошибок:
Однако как следует из первой строки все они имели одну первопричину:Код:CvGameCoreDLL\CvCity.cpp(4191): error C2065: 'pHeadSelectedCity' : undeclared identifier CvGameCoreDLL\CvCity.cpp(4191): error C2227: left of '->calculateActualYieldProduced' must point to class/struct/union type is ''unknown-type'' CvGameCoreDLL\CvCity.cpp(4205): error C2227: left of '->calculateNetYield' must point to class/struct/union type is ''unknown-type'' CvGameCoreDLL\CvCity.cpp(4191): error C2227: left of '->getBaseRawYieldProduced' must point to class/struct/union type is ''unknown-type'' CvGameCoreDLL\CvCity.cpp(4191): error C3861: 'pHeadSelectedCity': identifier not found, even with argument-dependent lookup CvGameCoreDLL\CvCity.cpp(4205): error C3861: 'pHeadSelectedCity': identifier not found, even with argument-dependent lookup
Я сначала по-дурости попытался выполнить "пожелания" программы-компилятора, а именно ввести и описать новую переменную 'pHeadSelectedCity'. Обычно такой трюк приводил меня в конце концов к успеху. После пары попыток мне действительно удалось это сделать и я смог без ошибок скомпилировать CvGameCoreDLL.dll. Однако вскоре оказалось, это был тупиковый путь. Мод с новой CvGameCoreDLL.dll запускался, но CvMainInterface.py естественно выдавал ошибку, поскольку TotalProducedYields не были правильно рассчитаны (если они вообще хоть как-то рассчитались).Код:'pHeadSelectedCity' : undeclared identifier
Поэтому мне ничего не оставалось как вернуться к моему старому способу и посмотреть как и где описывается, в частности
или нечто подобное иКод:pHeadSelectedCity->
или нечто подобное.Код:calculateActualYieldProduced((YieldTypes)iI)
Оказалось, что в CvCity.cpp вполне можно обойтись без pHeadSelectedCity->, что я незамедлительно и применил.
В итоге в патч были внесены небольшие изменения и сейчас эти участка кода выглядят так:иКод:// iUnproducedYield = pHeadSelectedCity->calculateActualYieldProduced((YieldTypes)iI) - pHeadSelectedCity->getBaseRawYieldProduced((YieldTypes)iI); //KJ closed due to error 'pHeadSelectedCity' : undeclared identifier iUnproducedYield = calculateActualYieldProduced((YieldTypes)iI) - getBaseRawYieldProduced((YieldTypes)iI); //KJ correction
В таком виде CvGameCoreDLL.dll компилируется без ошибок, мод запускается без проблем, а на городском экране все отражается правильно. По-видимому, так и должно быть.Код:// aiProducedYields[iI] += pHeadSelectedCity->calculateNetYield((YieldTypes)iI); //KJ closed due to error 'pHeadSelectedCity' : undeclared identifier aiProducedYields[iI] += calculateNetYield((YieldTypes)iI); //KJ correction
Посмотри, пожалуйста, еще разок на этот участок кода:
CvCity.cpp:
Если такие изменения допустимы, то я выложу версию с патчем. Заранее большое спасибо.
Да, так и должно быть. Просто при создании функции я скопировал алгоритм из подсказки и забыл поудалять pHeadSelectedCity->.
Если новые технологии позволяют обходится без услуг простых людей - это прогресс, а если новые технологии позволяют обходится без услуг миллионеров и крупных компаний - это нарушение авторских прав.
Мой мод
"New Colonists" ("Новые колонисты") версия 1.1: http://rghost.net/40682579
Если новые технологии позволяют обходится без услуг простых людей - это прогресс, а если новые технологии позволяют обходится без услуг миллионеров и крупных компаний - это нарушение авторских прав.
Мой мод
Привет, NeseryozniyVET!
У меня есть маленький вопрос по ресурсам.
Сейчас мы выводим на экран подсказку по исчерпаемым ресурсам в таком виде:
Тут сверху вниз идут:
Название ресурса (Россыпное золото)
Текуший запас месторождения: 40
Ресурс исчерпаемый
В CvGameTextMgr.cpp это выглядит так:
Насколько я понимаю тут логика предельно простая:Код:eBonus = pPlot->getBonusType(); if (eBonus != NO_BONUS) { szTempBuffer.Format(L"%c " SETCOLR L"%s" ENDCOLR, GC.getBonusInfo(eBonus).getChar(), TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getBonusInfo(eBonus).getDescription()); szString.append(NEWLINE); szString.append(szTempBuffer); // VET AmountResourses - begin 1/2 if (pPlot->getAmount() > 0) // если ресурс исчерпаемый { // szTempBuffer.Format(L" (%d)", pPlot->getAmount()); //KJ new format of data szString.append(CvWString::format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR))); //added by KJ szString.append(gDLL->getText("TXT_KEY_BONUS_STATUS")); //added by KJ szTempBuffer.Format(L" %d", pPlot->getAmount()); szString.append(szTempBuffer); // добавляем количество ресурсов в подсказку на экране szString.append(CvWString::format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR))); //added by KJ szString.append(gDLL->getText("TXT_KEY_AMOUNT_BONUS")); //added by KJ } // VET AmountResourses - end 1/2
Мне удалось ввести восполнимые ресурсы в твой код. А количественно восполнимые ресурсы могут как увеличиваться, так и уменьшаться. Для этого нужны новые по содержанию подсказки на экране (новые ссылки вместо TXT_KEY_BONUS_STATUS и TXT_KEY_AMOUNT_BONUS).if (eBonus != NO_BONUS) - если есть бонус, то ..... дальше по тексту.
Вот тут то и возник вопрос.
Как правильно прописать в CvGameTextMgr.cpp такое условие:
Я попробовал к примеру такой вариантесли есть BONUS_1 или BONUS_2 или BONUS_3
то ...... (вариант 1)
если есть BONUS_4 или BONUS_5 или BONUS_6
то ..... (вариант 2)
но ничего не получилось. CvGameCoreDLL.dll скомпилировалась без проблем, но подсказки вообще исчезли....Код:if (eBonus == ((BonusTypes)GC.getDefineINT("BONUS_1")) || (BonusTypes)GC.getDefineINT("BONUS_2")) || (BonusTypes)GC.getDefineINT("BONUS_3")))
Заранее большое спасибо!
Да, и еще маленькое дополнение. Снимок, который я привел в этом сообщении сделан из комбинированного мода, в котором я за пару часов соединил "Новых колонистов" и "Золотую лихорадку". Все прошло на удивление гладко и без единого бага!
Ну если бонусы прописаны в Enums.h то есть два варианта
1
2Код:if((eBonus == BONUS_1) || (eBonus == BONUS_2) || (eBonus == BONUS_3)) { вариант 1 } else if ((eBonus == BONUS_4) || (eBonus == BONUS_5) || (eBonus == BONUS_6)) { вариант 2 } else //все остальные бонусы, если для них нужен особый вариант { вариант 3 }
Выделеное красным можно не делать, если нету третьего вариантаКод:switch (eBonus) { case BONUS_1: case BONUS_2: case BONUS_3: { вариант 1 } break; case BONUS_4: case BONUS_5: case BONUS_6: { вариант 2 } break; default: //все остальные бонусы { вариант 3 } break; }
Если новые технологии позволяют обходится без услуг простых людей - это прогресс, а если новые технологии позволяют обходится без услуг миллионеров и крупных компаний - это нарушение авторских прав.
Мой мод
А разве бонусы когда-либо прописывались в CvEnums.h?
В исходных кодах для CivIV:BTS и CivIVColonization есть только такое описание:
Я уже пробовал вариант с выражением типаКод:enum BonusTypes // Exposed to Python { NO_BONUS = -1, };
но компилятор выдает ошибку. Причем именно на строке, где eBonus == BONUS_GOLD.Код:eBonus == BONUS_GOLD
Минуточку, сейчас еще разок проверю....
Вот попробовал так:
Здесь использовал выражение if (eBonus == BONUS_SILVER)Код:eBonus = pPlot->getBonusType(); //original // if (eBonus != NO_BONUS) //original if (eBonus == BONUS_SILVER) { szTempBuffer.Format(L"%c " SETCOLR L"%s" ENDCOLR, GC.getBonusInfo(eBonus).getChar(), TEXT_COLOR("COLOR_HIGHLIGHT_TEXT"), GC.getBonusInfo(eBonus).getDescription()); szString.append(NEWLINE); szString.append(szTempBuffer); // VET AmountResourses - begin 1/2 if (pPlot->getAmount() > 0) // если ресурс исчерпаемый { // szTempBuffer.Format(L" (%d)", pPlot->getAmount()); //KJ new format of data szString.append(CvWString::format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR))); //added by KJ szString.append(gDLL->getText("TXT_KEY_BONUS_STATUS")); //added by KJ szTempBuffer.Format(L" %d", pPlot->getAmount()); szString.append(szTempBuffer); // добавляем количество ресурсов в подсказку на экране szString.append(CvWString::format(L"\n%c", gDLL->getSymbolID(BULLET_CHAR))); //added by KJ szString.append(gDLL->getText("TXT_KEY_AMOUNT_BONUS")); //added by KJ } // VET AmountResourses - end 1/2 }
При компиляции произошла ошибка.
Строка номер 2279 это именно строка с if (eBonus == BONUS_SILVER).CvGameCoreDLL\CvGameTextMgr.cpp(2279): error C2065: 'BONUS_SILVER' : undeclared identifier
CvGameCoreDLL\CvGameTextMgr.cpp(2279): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'BonusTypes' (or there is no acceptable conversion)