00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00035
00036
00037
00038
00039
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042
00043 #include "stratagus.h"
00044 #include "video.h"
00045 #include "unittype.h"
00046 #include "animation.h"
00047 #include "player.h"
00048 #include "unit.h"
00049 #include "missile.h"
00050 #include "actions.h"
00051 #include "pathfinder.h"
00052 #include "sound.h"
00053 #include "map.h"
00054 #include "spells.h"
00055 #include "interface.h"
00056
00057
00058
00059
00060
00061 #if 0
00062
00068 void AnimateActionSpellCast(CUnit *unit)
00069 {
00070 int flags;
00071
00072 if (unit->Type->Animations) {
00073 Assert(unit->Type->Animations->Attack);
00074
00075 flags = UnitShowAnimation(unit, unit->Type->Animations->Attack);
00076
00077 if (flags & AnimationMissile) {
00078 FireMissile(unit);
00079 }
00080 }
00081 }
00082
00083 #endif
00084
00090 static void SpellMoveToTarget(CUnit *unit)
00091 {
00092 CUnit *goal;
00093 int err;
00094
00095
00096 err = 1;
00097 if (CanMove(unit)) {
00098 err = DoActionMove(unit);
00099 if (unit->Anim.Unbreakable) {
00100 return;
00101 }
00102 }
00103
00104
00105
00106 goal = unit->Orders[0]->Goal;
00107
00108 if (goal && MapDistanceBetweenUnits(unit, goal) <=
00109 unit->Orders[0]->Range) {
00110
00111
00112 unit->State = 0;
00113 UnitHeadingFromDeltaXY(unit,
00114 goal->X + (goal->Type->TileWidth - 1) / 2 - unit->X,
00115 goal->Y + (goal->Type->TileHeight - 1) / 2 - unit->Y);
00116 unit->SubAction++;
00117 return;
00118 } else if (!goal && MapDistanceToUnit(unit->Orders[0]->X,
00119 unit->Orders[0]->Y, unit) <= unit->Orders[0]->Range) {
00120
00121 UnitHeadingFromDeltaXY(unit,
00122 unit->Orders[0]->X + unit->Orders[0]->Arg1.Spell->Range - unit->X,
00123 unit->Orders[0]->Y + unit->Orders[0]->Arg1.Spell->Range - unit->Y);
00124 unit->SubAction++;
00125 return;
00126 } else if (err == PF_UNREACHABLE) {
00127
00128
00129
00130 unit->ClearAction();
00131 unit->State = 0;
00132
00133 if (unit->Orders[0]->Goal) {
00134 unit->Orders[0]->Goal->RefsDecrease();
00135 unit->Orders[0]->Goal = NoUnitP;
00136 }
00137 }
00138 Assert(!unit->Type->Vanishes && !unit->Destroyed);
00139 }
00140
00146 void HandleActionSpellCast(CUnit *unit)
00147 {
00148 int flags;
00149 const SpellType *spell;
00150
00151 if (unit->Wait) {
00152 unit->Wait--;
00153 return;
00154 }
00155
00156 switch (unit->SubAction) {
00157 case 0:
00158
00159
00160
00161 spell = unit->Orders[0]->Arg1.Spell;
00162 if (!CanCastSpell(unit, spell, unit->Orders[0]->Goal,
00163 unit->Orders[0]->X, unit->Orders[0]->Y)) {
00164
00165
00166
00167
00168 if (unit->Variable[MANA_INDEX].Value < spell->ManaCost) {
00169 unit->Player->Notify(NotifyYellow, unit->X, unit->Y,
00170 _("%s: not enough mana for spell: %s"),
00171 unit->Type->Name.c_str(), spell->Name.c_str());
00172 } else {
00173 unit->Player->Notify(NotifyYellow, unit->X, unit->Y,
00174 _("%s: can't cast spell: %s"),
00175 unit->Type->Name.c_str(), spell->Name.c_str());
00176 }
00177
00178 if (unit->Player->AiEnabled) {
00179 DebugPrint("FIXME: do we need an AI callback?\n");
00180 }
00181 unit->ClearAction();
00182 if (unit->Orders[0]->Goal) {
00183 unit->Orders[0]->Goal->RefsDecrease();
00184 unit->Orders[0]->Goal = NoUnitP;
00185 }
00186 return;
00187 }
00188
00189 NewResetPath(unit);
00190 unit->ReCast = 0;
00191 unit->SubAction = 1;
00192
00193 case 1:
00194 if ((spell = unit->Orders[0]->Arg1.Spell)->Range != INFINITE_RANGE) {
00195 SpellMoveToTarget(unit);
00196 break;
00197 } else {
00198 unit->SubAction = 2;
00199 }
00200
00201 case 2:
00202
00203 if (unit->Type->Animations->Attack) {
00204 flags = UnitShowAnimation(unit, unit->Type->Animations->Attack);
00205 if (unit->Anim.Unbreakable) {
00206 return;
00207 }
00208 } else {
00209
00210 if (unit->Orders[0]->Goal && !unit->Orders[0]->Goal->IsVisibleAsGoal(unit->Player)) {
00211 unit->ReCast = 0;
00212 } else {
00213 spell = unit->Orders[0]->Arg1.Spell;
00214 unit->ReCast = SpellCast(unit, spell, unit->Orders[0]->Goal,
00215 unit->Orders[0]->X, unit->Orders[0]->Y);
00216 }
00217 }
00218 if (!unit->ReCast && unit->Orders[0]->Action != UnitActionDie) {
00219 unit->ClearAction();
00220 if (unit->Orders[0]->Goal) {
00221 unit->Orders[0]->Goal->RefsDecrease();
00222 unit->Orders[0]->Goal = NoUnitP;
00223 }
00224 }
00225 break;
00226
00227 default:
00228 unit->SubAction = 0;
00229 break;
00230 }
00231 }
00232