


//---------------------------------------
// CONSTANTS
//---------------------------------------
const int SPL_TRANSFORM = 3;
const string SPL_DAMAGE_TEXT = "Урон: ";
const string SPL_DAMAGEPL_TEXT = "Урон за уровень: ";
const string SPL_COST_TEXT = "Стоимость: ";
const string SPL_COSTPL_TEXT = "Стоимость за уровень: ";
const string SPL_ENERGYTYPE = "Энергия: ";
const string SPL_HP = "Здоровье";
const string SPL_MP = "Мана";
const int SPL_DEFAULT = 0; //is DEFAULT spell
const int SPL_AREA = 1; //is area spell
const int SPL_SPREAD = 2; //is spread spell
//---------------------------------------
// CLASSES
//---------------------------------------
class C_SPELL_DATA
{
var string instName; //oCSpell objectname UNIQUE!
var int spellID; //unique spell ID > 500!
var string spellName; //Display name
var string spellAniName; //Cast animation
var string visualFxName; //VisualFX
var int damage; //Spell damage
var int cost; //Cost for rune
var int energyType; //Energy type
var int EffectType; //area/spread
};
//---------------------------------------
// PROTOTYPES
//---------------------------------------
PROTOTYPE C_SPL_DATA(C_SPELL_DATA)
{
instName = "Light";
spellID = 0;
spellName = "SPL_XXX";
spellAniName = "FBT";
visualFxName = "Light";
damage = 0;
cost = 0;
energyType = ATR_MANA;
EffectType = SPL_DEFAULT;
};
prototype NEW_Rune(C_Item)
{
name = "Руна";
mainflag = ITEM_KAT_RUNE;
flags = 0;
material = MAT_GLAS;
wear = WEAR_EFFECT;
effect = "";
text[1] = NAME_Manakosten;
text[5] = NAME_Value;
COUNT[5] = value;
};
const int SPL_FireRainN = 515;
const int SPL_Cost_Firerain = 15;
const int SPL_Damage_FireRain = 5;
//---------------------------------------
// Spell data instance
//---------------------------------------
instance Spell_FireRain_data (C_SPL_DATA)
{
instName = "Firerain";
spellID = SPL_FireRainN;
spellName = "Огненый дошть";
spellAniName = "HEA";
visualFxName = "FireRain";
damage = 10;
cost = SPL_Cost_Firerain;
energyType = ATR_MANA;
EffectType = SPL_AREA;
};
//---------------------------------------
// Spell Item
//---------------------------------------
instance ItRu_FireRain(C_Item)
{
name = NAME_Rune;
mainflag = ITEM_KAT_RUNE;
flags = 0;
value = 0;
visual = "ItRu_FireRain.3DS";
material = MAT_STONE;
spell = SPL_FireRainN;
wear = WEAR_EFFECT;
effect = "SPELLFX_WEAKGLIMMER_YELLOW";
description = "FireRain";
};
instance Spell_FireRain(C_Spell_Proto)
{
time_per_mana = 0;
damage_per_level = SPL_Damage_FireRain;
damagetype = DAM_MAGIC;
targetCollectAlgo = TARGET_COLLECT_ALL;
targetCollectRange = 100000;
isMultiEffect = TRUE;
};
func int Spell_Logic_Firerain(var int manaInvested)
{
if(Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
return SPL_SENDCAST;
}
else if(self.attribute[ATR_MANA] >= SPL_Cost_Firerain)
{
return SPL_SENDCAST;
}
else
{
return SPL_SENDSTOP;
};
};
func void Spell_Cast_Firerain()
{
if(Npc_GetActiveSpellIsScroll(self))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Firerain;
};
self.aivar[AIV_SelectSpell] += 1;
};
func int Spell_Collide_515()
{
if(self.guild < GIL_SEPERATOR_HUM)
{
var string msg;
msg = Str_Format("%s[%i] Spell_Collide_515", self.name, self.id);
Hlp_PrintConsole(msg);
};
return COLL_DOEVERYTHING;
};
| spellAniName | Примеры G1 | Примеры G2 | Примечание |
| "FIB" | DestroyUndead, BreathOfDeath, Firestorm, THUNDERBALL, Fireball | DestroyUndead, ChargeFireball, ChargeZap, BreathOfDeath, MasterOfDisaster | |
| "WND" | WindFist, STORMFIST | WindFist, LightningFlash, SuckEnergy, Geyser, Skull | |
| "FBT" | Firebolt, THUNDERBOLT | Plague, Swarm, IceLance, Zap, Icebolt, Firebolt, PalHolyBolt | |
| "FRZ" | ICECUBE | IceCube, GreenTentacle | |
| "LIN" | CHAINLIGHTNING | ||
| "FEA" | MassDeath, ICEWAVE, Firerain, Fear | Fear, Earthquake, Waterwall, Firerain, IceWave | |
| "TEL" | Telekinesis | ||
| "PYR" | Pyrokinesis | ||
| "CON" | Control | ||
| "SLE" | Light, Charm, Sleep, Shrink, Berzerk | Inflate, Light, Charm, Sleep, Shrink | |
| "TRF" | Transform | ||
| "HEA" | Heal, TELEPORT | Heal, TELEPORT | |
| "SUM" | Summon | Summon | |
| "WHI" | Whirlwind | ||
| "MSD" | MassDeath | ||
| "STM" | Thunderstorm |
C_CanNpcCollideWithSpell определяет, как будет реагировать конкретный npc, когда в него попадет конкретное заклинание.
COLL_DONOTHING - заклинание не подействует. Например, нельзя поджечь плывущего NPC.
COLL_DOEVERYTHING - полноценный обычный эффект. Полный урон, заморозка, горение и т.д.
COLL_APPLYDAMAGE - заклинание нанесет урон, но не будет вызван обработчик PERC_ASSESSMAGIC, т.е. не будет сопутствующих эффектов. Каменного голема нельзя заморозить или поджечь, охранник не взлетит в смерче.
COLL_APPLYHALVEDAMAGE - то же, плюс будет нанесена только половина урона (огненный шар на огненного голема).
COLL_APPLYDOUBLEDAMAGE - то же, но урон удвоенный (огонь против льда).
COLL_APPLYVICTIMSTATE - предположу, что как COLL_APPLYDAMAGE, но npc запомнит, что на него напали с магией (иначе реагирует как на обычное повреждение). Не используется, может и не работает.
COLL_DONTKILL - в результате действия заклинания npc не умирает, а падает без сознания (кулак ветра, воды, молния)

Флаг позволяет наложить дополнительный визуальный эффект на цель, заданный как emFXCollDynPerc_S (магическое горение, например).COLL_APPLYVICTIMSTATE - предположу, что как COLL_APPLYDAMAGE, но npc запомнит, что на него напали с магией (иначе реагирует как на обычное повреждение). Не используется, может и не работает.
попробовал огненный дождь. в Spell_Collide_515 зашёл один и тот же НПС.
что то не понял на что это влияетvar int cost; //Cost for rune
это проверка на то может ли нпс экипировать руну?const int spellID_TeleportADWENTRANC = 666; // должно быть более 500
instance ItRu_TeleportADWENTRANCE (C_Item)
{
ItRu_PalTeleportSecret();
visual = "ItAr_Rune_40.3ds";
spell = spellID_TeleportADWENTRANC;
};
instance Spell_Teleport_data(C_SPELL_DATA)
{
instName = "zTeleportADWENTRANCE"; // инстанция Spell_zTeleportADWENTRANCE
spellID = spellID_TeleportADWENTRANC; // ID. должно быть больше 500
spellName = NAME_SPL_PalTeleportSecret; // отображается на экране при переключение заклинаний
spellAniName = "HEA"; // "STM" "WHI" "MSD" "SLE" "HEA" "FBT" "FIB" "SUM" "TRF" "FEA" "FRZ"
visualFxName = "Teleport"; // spellFX_Teleport из файла VisualFxInst.d
damage = 0; // !!! урон !!!
cost = SPL_COST_TELEPORT; // хз что
energyType = ATR_MANA; // требует ману. может требовать жизни и хз что ещё
EffectType = zSPL_DEFAULT; // zSPL_DEFAULT или zSPL_AREA или zSPL_SPREAD или zSPL_TRANSFORM
};
// ------ Instanz fьr alle Teleport-Spells ------
INSTANCE Spell_zTeleportADWENTRANCE(C_Spell_Proto)
{
Spell_Teleport();
time_per_mana = 300; // Время в мс, требуемое для инвестирования 1 единицы маны?
};
func int Spell_Logic_zTeleportADWENTRANCE(var int manaInvested)
{
//if (manaInvested ==0 ) { return SPL_NEXTLEVEL; }; // "классичесий" вариант.
if (manaInvested == 0) { Spl_InvestNext(self); }; // "новый" вариант 1
//Spl_SetLevel(self,1); // "новый" вариант 2. для телепорта плохо
if (manaInvested > SPL_Cost_Teleport)
{
return SPL_SENDCAST;
};
return SPL_RECEIVEINVEST;
};
func void Spell_Cast_zTeleportADWENTRANCE()
{
if (CurrentLevel == ADDONWORLD_ZEN)
{
AI_Teleport (self, "ADW_ENTRANCE");
}
else if (CurrentLevel != DRAGONISLAND_ZEN)
{
Wld_ChangeLevel ("ADDON\ADDONWORLD.zen","ADW_ENTRANCE");
}
else
{
PrintScreen (PRINT_TeleportTooFarAway ,-1,YPOS_LevelUp,FONT_ScreenSmall,2);
};
AI_PlayAni (self, "T_HEASHOOT_2_STAND" );
};
time_per_mana встречается почти во всех заклинаниях Готики 1 и отвечает за скорость инвестирования маны. то есть сколько миллисекунд уйдёт на инвестирование 1 единицы маны.time_per_mana - благополучно не упоминается в гайдах, но, так как величина, отличная от 0 в этой строке встречается только в заряжаемых заклинаниях (типа Большого огненного шара или Кулака ветра), то, вероятно, отвечает за скорость расхода маны при зарядке каждой стадии; и это вряд ли секунды.
PROTOTYPE C_Spell_Proto(C_Spell) {
time_per_mana = 500; // Zeit pro investierten Manapunkt (ms)
в приведенном мною Spell_Logic ману отнимает движок. делает он это с определённой "скоростью", за эту "скорость" отвечает time_per_mana. что бы мана отнималась синхронно с анимацией каста я установил time_per_mana = 300. Можно поставить меньше. Можно поставить больше. Ставить 0 это халтура.В заклинаниях без зарядки, таких как телепорт - ставь там 0.
это на какое количество маны: 5, 10? сколько там анимация каста длится?я установил time_per_mana = 300
300 мс на 1 ману. 3000 мс на 10 маны. анимация подготовки к телепорту длинная: 2 с лишнем секунды.это на какое количество маны: 5, 10? сколько там анимация каста длится?
что значит "такое себе решение"? это оригинальная механика. хочешь делай халтурно и используй как ты и рекомендуешь time_per_mana = 0. в таком случае вся мана инвестируется мгновенно, а потом герой с уже потраченной манной будет делать вид что он якобы её тратит. хочешь разбирайся и определяй сколько времени требуется для того или иного заклинание на инвестирование единицы маны.Ну, такое себе решение с практической точки зрения
Делай как считаешь нужным. Но это не повод наводить тень на плетень на оригинальные механики.твоё право как автора делать модификацию такой какой тебе хочется. хочется тебе сделать 100 заклинаний за 10 минут - пожалуйста. и у такого принципа найдутся поклонники и сторонники. Мне лично нравится решение ElderGamer где увеличивается скорость инвестирования маны для свитков трансформации требующих много маны. и мне вообще нравится скрипты ElderGamer как раз потому что он вручную прорабатывает различные аспекты и ситуации, тратя на это колоссальное кол-во времени и сил. Я считаю что доработка логики с сохранением принципа это правильный путь. То есть когда есть общее понимание что заклинание не произносится мгновенно, а НПС инвестирует ману в него. и когда баланс меняет кол-венные показатели маны, увеличивая требования маны, можно увеличить и скорость инвестирования маны. И вот как раз для "сложных" свитков трансформации ElderGamer это и сделал. Что-то подобное я писал и для заклинания "контроль", изменяя скорость инвестирования маны в зависимости от того какой уровень у жертвы. Но это всё подразумевает "вручную корпеть", а в этом ты не видишь практического смысла :-DС практической точки зрения, на мой взгляд, смысла в том, чтобы вручную корпеть над тем, сколько длится анимация каждого конкретного заклинания такого типа и подстраивать инвестирование маны под него - нет.
понятия не имею. заметишь ли ты или нет. я думаю ты можешь придумать и реализовать такую ситуацию, при которой что то будет не заметно, а что то наоборот крайне заметно.У ГГ 400 маны, а свиток телепорта требует 5 - я замечу правильный расход маны на каст?
если ты про мой пример, то он сделан под руну телепорта и проверка в коде на то используется ли свиток отсутствует, ровно как и отсутствует инстанция свитка. таким образом отвечая на твой вопрос: да, эта ситуация учтена, в примере свиток телепорта отсутствует, отсутствует он осознанно.Свиток телепорта требует 5 маны, руна телепорта требует 50 маны - ситуация учтена в заклинании?
если в процессе инвестирования герой не сделает каст, то заклинание не состоится, при этом некоторое кол-во маны будет потрачено. "прервёт" заклинание движок и сделает это корректно, то есть мана не станет отрицательной и/или герой не зависит. если отнимать ману скриптами без доп проверок мана может стать отрицательной.Если в процессе инвестирования ГГ потеряет часть маны из-за внешних факторов (какие-нибудь проклятия или выжигания маны) - каст прервется? И насколько корректно прервется?
скорость инвестирования маны это не про механику магии ? а что это тогда? ненужная хрень из готики 1?Речи о механиках не было вообще.