Demolish action is now a spell.
This commit is contained in:
parent
b702d6b9ef
commit
21058caaf4
27 changed files with 88 additions and 492 deletions
doc
src
action
include
network
stratagus
ui
unit
|
@ -36,6 +36,7 @@
|
|||
<li>Future 2.00 Release<p>
|
||||
<ul>
|
||||
<li>++
|
||||
<li>Removed the demolish action, we now use the demolish spell. (from Crestez Leonard).
|
||||
<li>Applied patch #1969 (AI enhancement) (from Ludovic Pollet).
|
||||
<li>Added the demolish spell, though not complete (from Crestez Leonard).
|
||||
<li>Added the spawn-missile action, removed fireball death-coil whirlwind runes flame-shield (from Crestez Leonard).
|
||||
|
|
|
@ -311,6 +311,17 @@ Here are the supported operations, their paramenters, and what they do.<p>
|
|||
2 hit-points for 1 caster mana up to 20 hit-points/10 mana per cast
|
||||
</dd>
|
||||
</dl>
|
||||
<dt>demolish</dt>
|
||||
<dl>This will remove any trees/rocks/walls in and inflict a fixed damage
|
||||
to a fixed area. Possible tags:
|
||||
<dt>damage</dt>
|
||||
<dd>Each and every unit in range will receive that damage. FIXME: no
|
||||
support for dampening damage.
|
||||
</dd>
|
||||
<dt>range</dt>
|
||||
<dd>The range of the terrain and unit damage.
|
||||
</dd>
|
||||
</dl>
|
||||
<dt>summon</dt>
|
||||
<dl>This will summon a new unit. Possible tags:
|
||||
<dt>unit-type</dt>
|
||||
|
|
|
@ -326,9 +326,9 @@ F.E. "icon-knight", "icon-gold-mine".
|
|||
<dd>This should be used for resource gathering units. It will return goods when
|
||||
on a deposit and mine when on a resource.
|
||||
</dd>
|
||||
<dt>right-demolish</dt>
|
||||
<dd>This is for demolishing units. It will try to demolish instead of attack (since
|
||||
demolishing units can still have a normal attack, but it really shouldn't be used)
|
||||
<dt>right-spell-cast</dt>
|
||||
<dd>This is an ugly hack for demolishing units. The unit will cast it's first
|
||||
known spell(in order of spell definition) instead of attacking a hostile unit.
|
||||
</dd>
|
||||
<p></dl>
|
||||
<dt>can-gather-resource</dt>
|
||||
|
@ -462,13 +462,6 @@ F.E.: '( gold 2 wood 1 oil 1 ).
|
|||
<dt>detect-cloak</dt>
|
||||
<dd>Unit can detect cloaked units. If an unit is detected other units can attack it as well\
|
||||
</dd>
|
||||
<dt>demolish-range</dt>
|
||||
<dd>If non-zero this is the range for units that can demolish.The demolished area is a square, sorry.
|
||||
</dd>
|
||||
<dt>demolish-damage</dt>
|
||||
<dd>Damage dealt to unit affected by demolition. This can be 0, in this case
|
||||
only terrain will be affected. Units have to be in demolish-range to be affected.
|
||||
</dd>
|
||||
<dt>random-movement-probablitity</dt>
|
||||
<dd>When the unit is idle this is the probability that it will take a
|
||||
step in a random direction, in percents. Usefull for neutral animals.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
MODULE = src/action
|
||||
MSRC = action_attack.c action_board.c action_build.c action_demolish.c \
|
||||
MSRC = action_attack.c action_board.c action_build.c \
|
||||
action_die.c action_follow.c action_move.c action_patrol.c \
|
||||
action_repair.c action_research.c action_resource.c \
|
||||
action_returngoods.c action_spellcast.c action_stand.c \
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
// _________ __ __
|
||||
// / _____// |_____________ _/ |______ ____ __ __ ______
|
||||
// \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
|
||||
// / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
|
||||
// /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
|
||||
// \/ \/ \//_____/ \/
|
||||
// ______________________ ______________________
|
||||
// T H E W A R B E G I N S
|
||||
// Stratagus - A free fantasy real time strategy game engine
|
||||
//
|
||||
/**@name action_demolish.c - The demolish action. */
|
||||
//
|
||||
// (c) Copyright 1999-2001 by Vladi Belperchinov-Shabanski
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; version 2 dated June, 1991.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
//@{
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "unittype.h"
|
||||
#include "player.h"
|
||||
#include "unit.h"
|
||||
#include "actions.h"
|
||||
#include "sound.h"
|
||||
#include "map.h"
|
||||
#include "pathfinder.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
** Unit Demolishes
|
||||
**
|
||||
** @param unit Unit, for that the demolish is handled.
|
||||
*/
|
||||
global void HandleActionDemolish(Unit* unit)
|
||||
{
|
||||
Unit* table[UnitMax];
|
||||
int i;
|
||||
int n;
|
||||
int xmin;
|
||||
int ymin;
|
||||
int xmax;
|
||||
int ymax;
|
||||
int ix;
|
||||
int iy;
|
||||
Unit* goal;
|
||||
int err;
|
||||
|
||||
DebugLevel3Fn("Demolish %d\n" _C_ UnitNumber(unit));
|
||||
|
||||
switch (unit->SubAction) {
|
||||
//
|
||||
// Move near to target.
|
||||
//
|
||||
case 0: // first entry.
|
||||
NewResetPath(unit);
|
||||
unit->SubAction = 1;
|
||||
//
|
||||
// Already at target? FIXME: duplicate code.
|
||||
//
|
||||
if ((goal = unit->Orders[0].Goal)) {
|
||||
if (MapDistanceBetweenUnits(unit,goal) <= 1) {
|
||||
unit->State = 0;
|
||||
unit->SubAction = 2;
|
||||
HandleActionDemolish(unit);
|
||||
return;
|
||||
}
|
||||
} else if (MapDistanceToUnit(unit->Orders[0].X,
|
||||
unit->Orders[0].Y,unit) <= 1) {
|
||||
unit->State = 0;
|
||||
unit->SubAction = 2;
|
||||
HandleActionDemolish(unit);
|
||||
return;
|
||||
}
|
||||
// FALL THROUGH
|
||||
case 1:
|
||||
// FIXME: reset first!! why? (johns)
|
||||
err=DoActionMove(unit);
|
||||
if (unit->Reset) {
|
||||
goal = unit->Orders[0].Goal;
|
||||
//
|
||||
// Target is dead, stop demolish.
|
||||
// FIXME: what should I do, go back or explode on place?
|
||||
//
|
||||
if (goal) {
|
||||
if (goal->Destroyed) {
|
||||
DebugLevel0Fn("Destroyed unit\n");
|
||||
RefsDebugCheck(!goal->Refs);
|
||||
if (!--goal->Refs) {
|
||||
ReleaseUnit(goal);
|
||||
}
|
||||
// FIXME: perhaps I should choose an alternative
|
||||
unit->Orders[0].Goal = NoUnitP;
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->SubAction = 0;
|
||||
return;
|
||||
} else if (goal->Removed || !goal->HP ||
|
||||
goal->Orders[0].Action == UnitActionDie) {
|
||||
RefsDebugCheck(!goal->Refs);
|
||||
--goal->Refs;
|
||||
RefsDebugCheck(!goal->Refs);
|
||||
unit->Orders[0].Goal = NoUnitP;
|
||||
// FIXME: perhaps I should choose an alternative
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->SubAction = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Have reached target? FIXME: could use pathfinder result?
|
||||
//
|
||||
if (goal) {
|
||||
if (MapDistanceBetweenUnits(unit, goal) <= 1) {
|
||||
unit->State = 0;
|
||||
unit->SubAction = 2;
|
||||
}
|
||||
} else if (MapDistanceToUnit(unit->Orders[0].X, unit->Orders[0].Y,
|
||||
unit) <= 1) {
|
||||
unit->State = 0;
|
||||
unit->SubAction = 2;
|
||||
} else if (err == PF_UNREACHABLE) {
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
return;
|
||||
}
|
||||
DebugCheck(unit->Orders[0].Action != UnitActionDemolish);
|
||||
}
|
||||
break;
|
||||
|
||||
//
|
||||
// Demolish the target.
|
||||
//
|
||||
case 2:
|
||||
goal = unit->Orders[0].Goal;
|
||||
if (goal) {
|
||||
RefsDebugCheck(!goal->Refs);
|
||||
--goal->Refs;
|
||||
RefsDebugCheck(!goal->Refs);
|
||||
unit->Orders[0].Goal = NoUnitP;
|
||||
}
|
||||
|
||||
if (unit->Type->DemolishRange) {
|
||||
xmin = unit->X - unit->Type->DemolishRange;
|
||||
ymin = unit->Y - unit->Type->DemolishRange;
|
||||
xmax = unit->X + unit->Type->DemolishRange;
|
||||
ymax = unit->Y + unit->Type->DemolishRange;
|
||||
if (xmin < 0) {
|
||||
xmin = 0;
|
||||
}
|
||||
if (xmax > TheMap.Width - 1) {
|
||||
xmax = TheMap.Width - 1;
|
||||
}
|
||||
if (ymin < 0) {
|
||||
ymin = 0;
|
||||
}
|
||||
if (ymax > TheMap.Height - 1) {
|
||||
ymax = TheMap.Height - 1;
|
||||
}
|
||||
|
||||
// FIXME: Must play explosion sound
|
||||
|
||||
//
|
||||
// Effect of the explosion on units. Don't bother if damage is 0
|
||||
//
|
||||
if (unit->Type->DemolishDamage) {
|
||||
n = SelectUnits(xmin, ymin, xmax, ymax, table);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (table[i]->Type->UnitType != UnitTypeFly &&
|
||||
table[i]->HP && table[i] != unit &&
|
||||
MapDistanceBetweenUnits(unit, table[i]) <=
|
||||
unit->Type->DemolishRange) {
|
||||
// Don't hit flying units!
|
||||
HitUnit(unit, table[i], unit->Type->DemolishDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Terrain effect of the explosion
|
||||
//
|
||||
for (ix = xmin; ix <= xmax; ++ix) {
|
||||
for (iy = ymin; iy <= ymax; ++iy) {
|
||||
n = TheMap.Fields[ix + iy * TheMap.Width].Flags;
|
||||
if (MapDistanceToUnit(ix, iy, unit) >
|
||||
unit->Type->DemolishRange) {
|
||||
// Not in circle range
|
||||
continue;
|
||||
} else if (n & MapFieldWall) {
|
||||
MapRemoveWall(ix, iy);
|
||||
} else if (n & MapFieldRocks) {
|
||||
MapRemoveRock(ix, iy);
|
||||
} else if (n & MapFieldForest) {
|
||||
MapRemoveWood(ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LetUnitDie(unit);
|
||||
#ifdef HIERARCHIC_PATHFINDER
|
||||
PfHierMapChangedCallback (xmin, ymin, xmax, ymax);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
|
@ -95,6 +95,7 @@ global void AnimateActionSpellCast(Unit* unit)
|
|||
*/
|
||||
local void SpellMoveToTarget(Unit* unit)
|
||||
{
|
||||
SpellType* spell;
|
||||
Unit* goal;
|
||||
int err;
|
||||
|
||||
|
@ -139,17 +140,29 @@ local void SpellMoveToTarget(Unit* unit)
|
|||
unit->SubAction++; // cast the spell
|
||||
return;
|
||||
} else if (err) {
|
||||
// goal/spot out of range -- move to target
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->State = unit->SubAction = 0;
|
||||
//
|
||||
// Target self-> we don't really have to get in range,
|
||||
// just as close as possible, since the spell is centered
|
||||
// on the caster anyway.
|
||||
//
|
||||
if ((spell = unit->Orders[0].Arg1)->Target == TargetSelf) {
|
||||
DebugLevel0Fn("Increase range for spellcast.");
|
||||
unit->Orders->Range++;
|
||||
} else {
|
||||
//
|
||||
// goal/spot out of range -- give up
|
||||
//
|
||||
unit->Orders[0].Action = UnitActionStill;
|
||||
unit->State = unit->SubAction = 0;
|
||||
|
||||
if (unit->Orders[0].Goal) { // Release references
|
||||
RefsDebugCheck(!unit->Orders[0].Goal->Refs);
|
||||
if (!--unit->Orders[0].Goal->Refs) {
|
||||
RefsDebugCheck(!unit->Orders[0].Goal->Destroyed);
|
||||
ReleaseUnit(unit->Orders[0].Goal);
|
||||
if (unit->Orders[0].Goal) { // Release references
|
||||
RefsDebugCheck(!unit->Orders[0].Goal->Refs);
|
||||
if (!--unit->Orders[0].Goal->Refs) {
|
||||
RefsDebugCheck(!unit->Orders[0].Goal->Destroyed);
|
||||
ReleaseUnit(unit->Orders[0].Goal);
|
||||
}
|
||||
unit->Orders[0].Goal = NoUnitP;
|
||||
}
|
||||
unit->Orders[0].Goal = NoUnitP;
|
||||
}
|
||||
}
|
||||
DebugCheck(unit->Type->Vanishes || unit->Destroyed);
|
||||
|
|
|
@ -177,7 +177,7 @@ local void (*HandleActionTable[256])(Unit*) = {
|
|||
HandleActionRepair,
|
||||
HandleActionResource,
|
||||
HandleActionReturnGoods,
|
||||
HandleActionDemolish,
|
||||
HandleActionNotWritten,
|
||||
HandleActionNotWritten,
|
||||
|
||||
// Enough for the future ?
|
||||
|
|
|
@ -1159,74 +1159,6 @@ global void CommandCancelResearch(Unit* unit)
|
|||
ClearSavedAction(unit);
|
||||
}
|
||||
|
||||
/**
|
||||
** Demolish at position
|
||||
**
|
||||
** @param unit pointer to unit.
|
||||
** @param x X map position to move to.
|
||||
** @param y Y map position to move to.
|
||||
** @param dest if != NULL, pointer to unit to destroy.
|
||||
** @param flush if true, flush command queue.
|
||||
*/
|
||||
global void CommandDemolish(Unit* unit, int x, int y, Unit* dest, int flush)
|
||||
{
|
||||
Order* order;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (x < 0 || y < 0 || x >= TheMap.Width || y >= TheMap.Height) {
|
||||
DebugLevel0Fn("Internal movement error\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Check if unit is still valid? (NETWORK!)
|
||||
//
|
||||
if (!unit->Removed && unit->Orders[0].Action != UnitActionDie) {
|
||||
if (unit->Type->Building) {
|
||||
// FIXME: should find a better way for pending orders.
|
||||
order = &unit->NewOrder;
|
||||
ReleaseOrder(order);
|
||||
} else if (!(order = GetNextOrder(unit, flush))) {
|
||||
return;
|
||||
}
|
||||
|
||||
order->Action = UnitActionDemolish;
|
||||
if (dest) {
|
||||
//
|
||||
// Destination could be killed.
|
||||
// Should be handled in action, but is not possible!
|
||||
// Unit::Refs is used as timeout counter.
|
||||
//
|
||||
if (dest->Destroyed) {
|
||||
order->X = dest->X + dest->Type->TileWidth / 2;
|
||||
order->Y = dest->Y + dest->Type->TileHeight / 2;
|
||||
order->Goal = NoUnitP;
|
||||
order->Range = 0;
|
||||
} else {
|
||||
order->X = order->Y = -1;
|
||||
order->Goal = dest;
|
||||
RefsDebugCheck(!dest->Refs);
|
||||
dest->Refs++;
|
||||
order->Range = 1;
|
||||
}
|
||||
} else if (WallOnMap(x,y) || ForestOnMap(x,y) || RockOnMap(x,y)) {
|
||||
order->X = x;
|
||||
order->Y = y;
|
||||
order->Range = 1;
|
||||
order->Goal = NoUnitP;
|
||||
} else {
|
||||
order->X = x;
|
||||
order->Y = y;
|
||||
order->Range = 0;
|
||||
order->Goal = NoUnitP;
|
||||
}
|
||||
order->Type = NULL;
|
||||
order->Arg1 = NULL;
|
||||
}
|
||||
ClearSavedAction(unit);
|
||||
}
|
||||
|
||||
/**
|
||||
** Cast a spell at position or unit.
|
||||
**
|
||||
|
|
|
@ -121,8 +121,6 @@ extern void CommandResearch(Unit* unit,Upgrade* what,int flush);
|
|||
extern void CommandCancelResearch(Unit* unit);
|
||||
/// Prepare command upgrade
|
||||
//extern void CommandUpgradeUnit(Unit* unit,int what,int flush);
|
||||
/// Prepare command demolish
|
||||
extern void CommandDemolish(Unit* unit,int x,int y,Unit* dest,int flush);
|
||||
/// Prepare command spellcast
|
||||
extern void CommandSpellCast(Unit* unit,int x,int y,Unit* dest
|
||||
,SpellType* spell,int flush);
|
||||
|
@ -179,8 +177,6 @@ extern void HandleActionUpgradeTo(Unit* unit);
|
|||
extern void HandleActionUpgrade(Unit* unit);
|
||||
/// Handle command research
|
||||
extern void HandleActionResearch(Unit* unit);
|
||||
/// Handle command demolish
|
||||
extern void HandleActionDemolish(Unit* unit);
|
||||
/// Handle command spellcast
|
||||
extern void HandleActionSpellCast(Unit* unit);
|
||||
|
||||
|
|
|
@ -116,8 +116,6 @@ extern void SendCommandCancelUpgradeTo(Unit* unit);
|
|||
extern void SendCommandResearch(Unit* unit,Upgrade* what,int flush);
|
||||
/// Send cancel research command
|
||||
extern void SendCommandCancelResearch(Unit* unit);
|
||||
/// Send demolish command
|
||||
extern void SendCommandDemolish(Unit* unit,int x,int y,Unit* dest,int flush);
|
||||
/// Send spell cast command
|
||||
extern void SendCommandSpellCast(Unit* unit,int x,int y,Unit* dest,int spellid
|
||||
,int flush);
|
||||
|
|
|
@ -47,16 +47,15 @@
|
|||
|
||||
/// Button Commands that need target selection
|
||||
enum _button_cmd_ {
|
||||
ButtonMove, /// order move
|
||||
ButtonAttack, /// order attack
|
||||
ButtonRepair, /// order repair
|
||||
ButtonHarvest, /// order harvest
|
||||
ButtonBuild, /// order build
|
||||
ButtonPatrol, /// order patrol
|
||||
ButtonAttackGround, /// order attack ground
|
||||
ButtonSpellCast, /// order cast spell
|
||||
ButtonUnload, /// order unload unit
|
||||
ButtonDemolish, /// order demolish/explode
|
||||
ButtonMove, /// order move
|
||||
ButtonAttack, /// order attack
|
||||
ButtonRepair, /// order repair
|
||||
ButtonHarvest, /// order harvest
|
||||
ButtonBuild, /// order build
|
||||
ButtonPatrol, /// order patrol
|
||||
ButtonAttackGround, /// order attack ground
|
||||
ButtonSpellCast, /// order cast spell
|
||||
ButtonUnload, /// order unload unit
|
||||
ButtonStop, /// order stop
|
||||
ButtonButton, /// choose other button set
|
||||
ButtonTrain, /// order train
|
||||
|
|
|
@ -93,7 +93,6 @@ enum _message_type_ {
|
|||
MessageCommandCancelUpgrade, /// Unit command cancel upgrade
|
||||
MessageCommandResearch, /// Unit command research
|
||||
MessageCommandCancelResearch, /// Unit command cancel research
|
||||
MessageCommandDemolish, /// Unit command demolish
|
||||
|
||||
MessageExtendedCommand, /// Command is the next byte
|
||||
|
||||
|
|
|
@ -421,9 +421,7 @@ enum _unit_action_ {
|
|||
|
||||
UnitActionRepair, /// unit repairing
|
||||
UnitActionResource, /// unit harvesting resources
|
||||
UnitActionReturnGoods, /// unit returning any resource
|
||||
|
||||
UnitActionDemolish, /// unit demolish at position/unit
|
||||
UnitActionReturnGoods /// unit returning any resource
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -257,17 +257,6 @@
|
|||
**
|
||||
** How many points you get for unit. Used in the final score table.
|
||||
**
|
||||
** UnitType::DemolishRange
|
||||
**
|
||||
** If non-zero This is the range for units that can demolish.
|
||||
** The demolished area is a square, sorry.
|
||||
**
|
||||
** UnitType::DemolishDamage
|
||||
**
|
||||
** Damage dealt to unit affected by demolition. This can be 0,
|
||||
** in this case only terrain will be affected. Units have to be in
|
||||
** DemolishRange to be affected.
|
||||
**
|
||||
** UnitType::CanTarget
|
||||
**
|
||||
** Which units can it attack
|
||||
|
@ -712,8 +701,6 @@ struct _unit_type_ {
|
|||
int _BasicDamage; /// Basic damage dealt
|
||||
int _PiercingDamage; /// Piercing damage dealt
|
||||
int _RegenerationRate; /// HP regeneration HP per sec
|
||||
int DemolishRange; /// Unit will Demolish around when dead.
|
||||
int DemolishDamage; /// Damage dealt to unit affected by demolition.
|
||||
int RepairRange; /// Units repair range.
|
||||
char *CanCastSpell; /// Unit is able to use spells.
|
||||
// FIXME: n0body: AutoBuildRate not implemented.
|
||||
|
@ -735,7 +722,7 @@ struct _unit_type_ {
|
|||
#define MouseActionAttack 1 /// Attack
|
||||
#define MouseActionMove 2 /// Move
|
||||
#define MouseActionHarvest 3 /// Harvest resources
|
||||
#define MouseActionDemolish 5 /// Demolish
|
||||
#define MouseActionSpellCast 5 /// Cast the first spell known
|
||||
#define MouseActionSail 6 /// Sail
|
||||
int Points; /// How many points you get for unit
|
||||
int CanTarget; /// Which units can it attack
|
||||
|
|
|
@ -577,8 +577,6 @@ local void DoNextReplay(void)
|
|||
SendCommandResearch(UnitSlots[unit],UpgradeByIdent(val), flags);
|
||||
} else if (!strcmp(name, "cancel-research")) {
|
||||
SendCommandCancelResearch(UnitSlots[unit]);
|
||||
} else if (!strcmp(name, "demolish")) {
|
||||
SendCommandDemolish(UnitSlots[unit], posx, posy, dunit, flags);
|
||||
} else if (!strcmp(name, "spell-cast")) {
|
||||
SendCommandSpellCast(UnitSlots[unit], posx, posy, dunit, num, flags);
|
||||
} else if (!strcmp(name, "auto-spell-cast")) {
|
||||
|
@ -1055,25 +1053,6 @@ global void SendCommandCancelResearch(Unit* unit)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Send command: Unit demolish at position.
|
||||
**
|
||||
** @param unit pointer to unit.
|
||||
** @param x X map tile position where to demolish.
|
||||
** @param y Y map tile position where to demolish.
|
||||
** @param attack or !=NoUnitP unit to be demolished.
|
||||
** @param flush Flag flush all pending commands.
|
||||
*/
|
||||
global void SendCommandDemolish(Unit* unit, int x, int y, Unit* attack, int flush)
|
||||
{
|
||||
if (NetworkFildes == (Socket)-1) {
|
||||
CommandLog("demolish", unit, flush, x, y, attack, NULL, -1);
|
||||
CommandDemolish(unit, x, y, attack, flush);
|
||||
} else {
|
||||
NetworkSendCommand(MessageCommandDemolish, unit, x, y, attack, NULL, flush);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Send command: Unit spell cast on position/unit.
|
||||
**
|
||||
|
@ -1365,15 +1344,6 @@ global void ParseCommand(unsigned char msgnr, UnitRef unum,
|
|||
NULL, -1);
|
||||
CommandCancelResearch(unit);
|
||||
break;
|
||||
case MessageCommandDemolish:
|
||||
dest = NoUnitP;
|
||||
if (dstnr != (unsigned short)0xFFFF) {
|
||||
dest = UnitSlots[dstnr];
|
||||
DebugCheck(!dest || !dest->Type);
|
||||
}
|
||||
CommandLog("demolish", unit, status, x, y, dest, NULL, -1);
|
||||
CommandDemolish(unit, x, y, dest, status);
|
||||
break;
|
||||
default:
|
||||
id = (msgnr&0x7f) - MessageCommandSpellCast;
|
||||
if (y != (unsigned short)0xFFFF) {
|
||||
|
|
|
@ -104,7 +104,7 @@ local void HandleSuicideClick(Unit* unit)
|
|||
|
||||
// FIXME: make this configurable
|
||||
if (unit->Value == unit->Type->ClicksToExplode) {
|
||||
SendCommandDemolish(unit, unit->X, unit->Y, 0, FlushCommands);
|
||||
LetUnitDie(unit);
|
||||
unit->Value = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,10 +109,13 @@ global int CastDemolish(Unit* caster, const SpellType* spell __attribute__((unus
|
|||
int n;
|
||||
Unit* table[UnitMax];
|
||||
|
||||
xmin = x - action->Data.Demolish.Range;
|
||||
ymin = y - action->Data.Demolish.Range;
|
||||
xmax = x + action->Data.Demolish.Range;
|
||||
ymax = y + action->Data.Demolish.Range;
|
||||
//
|
||||
// Allow error margnins. (Lame, I know)
|
||||
//
|
||||
xmin = x - action->Data.Demolish.Range - 2;
|
||||
ymin = y - action->Data.Demolish.Range - 2;
|
||||
xmax = x + action->Data.Demolish.Range + 2;
|
||||
ymax = y + action->Data.Demolish.Range + 2;
|
||||
if (xmin < 0) {
|
||||
xmin = 0;
|
||||
}
|
||||
|
@ -130,9 +133,9 @@ global int CastDemolish(Unit* caster, const SpellType* spell __attribute__((unus
|
|||
// Effect of the explosion on units. Don't bother if damage is 0
|
||||
//
|
||||
if (action->Data.Demolish.Damage) {
|
||||
n = SelectUnits(xmin, ymin, xmax+1, ymax+1, table);
|
||||
n = SelectUnits(xmin, ymin, xmax, ymax, table);
|
||||
for (i = 0; i < n; ++i) {
|
||||
DebugLevel0("Hit an unit at %d %d?\n" _C_ table[i]->X _C_ table[i]->Y);
|
||||
DebugLevel3("Hit an unit at %d %d?\n" _C_ table[i]->X _C_ table[i]->Y);
|
||||
if (table[i]->Type->UnitType != UnitTypeFly && table[i]->HP &&
|
||||
MapDistanceToUnit(x, y, table[i]) <= action->Data.Demolish.Range) {
|
||||
// Don't hit flying units!
|
||||
|
@ -1137,6 +1140,14 @@ global int SpellCast(Unit* caster, const SpellType* spell, Unit* target,
|
|||
x += spell->Range; // Why ??
|
||||
y += spell->Range; // Why ??
|
||||
}
|
||||
//
|
||||
// For TargetSelf, you target.... YOURSELF
|
||||
//
|
||||
if (spell->Target==TargetSelf) {
|
||||
x=caster->X;
|
||||
y=caster->Y;
|
||||
target=caster;
|
||||
}
|
||||
DebugLevel3Fn("Spell cast: (%s), %s -> %s (%d,%d)\n" _C_ spell->IdentName _C_
|
||||
unit->Type->Name _C_ target ? target->Type->Name : "none" _C_ x _C_ y);
|
||||
if (CanCastSpell(caster, spell, target, x, y)) {
|
||||
|
|
|
@ -135,8 +135,6 @@ global void SaveButtons(CLFile* file)
|
|||
CLprintf(file, "'attack-ground"); break;
|
||||
case ButtonReturn:
|
||||
CLprintf(file, "'return-goods"); break;
|
||||
case ButtonDemolish:
|
||||
CLprintf(file, "'demolish"); break;
|
||||
case ButtonSpellCast:
|
||||
CLprintf(file, "'cast-spell"); break;
|
||||
case ButtonResearch:
|
||||
|
@ -431,9 +429,6 @@ global void DrawButtonPanel(void)
|
|||
case ButtonAttack:
|
||||
action = UnitActionAttack;
|
||||
break;
|
||||
case ButtonDemolish:
|
||||
action = UnitActionDemolish;
|
||||
break;
|
||||
case ButtonAttackGround:
|
||||
action = UnitActionAttackGround;
|
||||
break;
|
||||
|
@ -616,13 +611,6 @@ local void UpdateButtonPanelMultipleUnits(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else if (UnitButtonTable[z]->Action == ButtonDemolish) {
|
||||
for (i = NumSelected; --i;) {
|
||||
if (Selected[i]->Type->Volatile) {
|
||||
allow = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (UnitButtonTable[z]->Action == ButtonCancel) {
|
||||
allow = 1;
|
||||
} else if (UnitButtonTable[z]->Action == ButtonCancelUpgrade) {
|
||||
|
@ -784,11 +772,6 @@ global void UpdateButtonPanel(void)
|
|||
allow = 1;
|
||||
}
|
||||
break;
|
||||
case ButtonDemolish:
|
||||
if (Selected[0]->Type->Volatile) {
|
||||
allow = 1;
|
||||
}
|
||||
break;
|
||||
case ButtonTrain:
|
||||
// Check if building queue is enabled
|
||||
if (!EnableTrainingQueue &&
|
||||
|
@ -890,7 +873,6 @@ global void DoButtonButtonClicked(int button)
|
|||
case ButtonAttack:
|
||||
case ButtonRepair:
|
||||
case ButtonAttackGround:
|
||||
case ButtonDemolish:
|
||||
case ButtonSpellCast:
|
||||
if (CurrentButtons[button].Action == ButtonSpellCast &&
|
||||
(KeyModifiers & ModifierControl)) {
|
||||
|
|
|
@ -527,7 +527,10 @@ global void DrawUnitInfo(const Unit* unit)
|
|||
}
|
||||
|
||||
}
|
||||
if (type->CanCastSpell) {
|
||||
//
|
||||
// Unit can cast spell without mana, so only show mana bar for units with mana
|
||||
//
|
||||
if (type->_MaxMana) {
|
||||
if (0) {
|
||||
VideoDrawText(x + 59, y + 8 + 140 + 1, GameFont, "Magic:");
|
||||
VideoDrawRectangleClip(ColorGray, x + 108, y + 8 + 140, 61, 14);
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "sound.h"
|
||||
#include "ui.h"
|
||||
#include "network.h"
|
||||
#include "spells.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
|
@ -110,6 +111,7 @@ global void DoRightButton(int sx, int sy)
|
|||
int acknowledged;
|
||||
int flush;
|
||||
int res;
|
||||
int spellnum;
|
||||
|
||||
//
|
||||
// No unit selected
|
||||
|
@ -259,13 +261,17 @@ global void DoRightButton(int sx, int sy)
|
|||
//
|
||||
// Fighters
|
||||
//
|
||||
if (action == MouseActionDemolish || action == MouseActionAttack) {
|
||||
if (action == MouseActionSpellCast || action == MouseActionAttack) {
|
||||
if (dest) {
|
||||
if (IsEnemy(unit->Player, dest)) {
|
||||
dest->Blink = 4;
|
||||
if (action == MouseActionDemolish) {
|
||||
if (action == MouseActionSpellCast) {
|
||||
// This is for demolition squads and such
|
||||
SendCommandDemolish(unit, x, y, dest, flush);
|
||||
DebugCheck(!unit->Type->CanCastSpell);
|
||||
for (spellnum=0; !unit->Type->CanCastSpell[spellnum] &&
|
||||
spellnum < SpellTypeCount ; spellnum++) ;
|
||||
DebugCheck(spellnum == SpellTypeCount);
|
||||
SendCommandSpellCast(unit, x, y, dest, spellnum, flush);
|
||||
} else {
|
||||
SendCommandAttack(unit, x, y, dest, flush);
|
||||
}
|
||||
|
@ -945,39 +951,6 @@ local void SendPatrol(int sx, int sy)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Let a unit explode at selected point
|
||||
**
|
||||
** @param sx X screen map position
|
||||
** @param sy Y screen map position
|
||||
*/
|
||||
local void SendDemolish(int sx, int sy)
|
||||
{
|
||||
int i;
|
||||
Unit* unit;
|
||||
Unit* dest;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
x = sx / TileSizeX;
|
||||
y = sy / TileSizeY;
|
||||
for (i = 0; i < NumSelected; ++i) {
|
||||
unit = Selected[i];
|
||||
if (unit->Type->Volatile) {
|
||||
// FIXME: choose correct unit no flying ...
|
||||
if ((dest = UnitUnderCursor) && CanTarget(unit->Type, dest->Type)) {
|
||||
dest->Blink = 4;
|
||||
} else {
|
||||
dest = NoUnitP;
|
||||
}
|
||||
SendCommandDemolish(unit, sx / TileSizeX, sy / TileSizeY, dest,
|
||||
!(KeyModifiers & ModifierShift));
|
||||
} else {
|
||||
DebugLevel0Fn("can't demolish %p\n" _C_ unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Let units harvest wood/mine gold/haul oil
|
||||
**
|
||||
|
@ -1119,9 +1092,6 @@ local void SendCommand(int sx, int sy)
|
|||
case ButtonUnload:
|
||||
SendUnload(sx, sy);
|
||||
break;
|
||||
case ButtonDemolish:
|
||||
SendDemolish(sx, sy);
|
||||
break;
|
||||
case ButtonSpellCast:
|
||||
SendSpellCast(sx, sy);
|
||||
break;
|
||||
|
|
|
@ -2785,8 +2785,6 @@ local SCM CclDefineButton(SCM list)
|
|||
ba.Action = ButtonAttackGround;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("return-goods"))) {
|
||||
ba.Action = ButtonReturn;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("demolish"))) {
|
||||
ba.Action = ButtonDemolish;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("cast-spell"))) {
|
||||
ba.Action = ButtonSpellCast;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("research"))) {
|
||||
|
|
|
@ -215,8 +215,6 @@ local void CclParseOrder(SCM list,Order* order)
|
|||
order->Action = UnitActionResource;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("action-return-goods"))) {
|
||||
order->Action = UnitActionReturnGoods;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("action-demolish"))) {
|
||||
order->Action = UnitActionDemolish;
|
||||
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("flags"))) {
|
||||
value = gh_car(list);
|
||||
|
|
|
@ -364,8 +364,8 @@ local SCM CclDefineUnitType(SCM list)
|
|||
type->MouseAction = MouseActionMove;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("right-harvest"))) {
|
||||
type->MouseAction = MouseActionHarvest;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("right-demolish"))) {
|
||||
type->MouseAction = MouseActionDemolish;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("right-spell-cast"))) {
|
||||
type->MouseAction = MouseActionSpellCast;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("right-sail"))) {
|
||||
type->MouseAction = MouseActionSail;
|
||||
|
||||
|
@ -373,12 +373,6 @@ local SCM CclDefineUnitType(SCM list)
|
|||
type->GroundAttack = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("can-attack"))) {
|
||||
type->CanAttack = 1;
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("demolish-range"))){
|
||||
type->DemolishRange = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("demolish-damage"))){
|
||||
type->DemolishDamage = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
} else if (gh_eq_p(value, gh_symbol2scm("repair-range"))) {
|
||||
type->RepairRange = gh_scm2int(gh_car(list));
|
||||
list = gh_cdr(list);
|
||||
|
@ -595,14 +589,6 @@ local SCM CclDefineUnitType(SCM list)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Unit type checks.
|
||||
//
|
||||
if (type->CanCastSpell && !type->_MaxMana) {
|
||||
DebugLevel0Fn("%s: Need max mana value\n" _C_ type->Ident);
|
||||
type->_MaxMana = 1;
|
||||
}
|
||||
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
|
|
|
@ -3424,10 +3424,6 @@ local void SaveOrder(const Order* order, CLFile* file)
|
|||
CLprintf(file, "action-return-goods");
|
||||
break;
|
||||
|
||||
case UnitActionDemolish:
|
||||
CLprintf(file, "action-demolish");
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugLevel0Fn("Unknown action in order\n");
|
||||
}
|
||||
|
|
|
@ -1485,11 +1485,6 @@ local void ShowSingleOrder(const Unit* unit, int x1, int y1, const Order* order)
|
|||
dest = 1;
|
||||
break;
|
||||
|
||||
case UnitActionDemolish:
|
||||
e_color = color = ColorRed;
|
||||
dest = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
e_color = color = ColorGray;
|
||||
DebugLevel1Fn("Unknown action %d\n" _C_ order->Action);
|
||||
|
|
|
@ -507,13 +507,6 @@ global void ParsePudUDTA(const char* udta, int length __attribute__((unused)))
|
|||
if (BIT(31, v)) DebugLevel0("Unused bit 31 used in %d\n" _C_ i);
|
||||
#endif
|
||||
#undef BIT
|
||||
//
|
||||
// Unit type checks.
|
||||
//
|
||||
if (unittype->CanCastSpell && !unittype->_MaxMana) {
|
||||
DebugLevel0Fn("%s: Need max mana value\n" _C_ unittype->Ident);
|
||||
unittype->_MaxMana = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: peon applies also to peon-with-gold and peon-with-wood
|
||||
|
@ -851,8 +844,8 @@ local void SaveUnitType(CLFile* file, const UnitType* type, int all)
|
|||
case MouseActionHarvest:
|
||||
CLprintf(file, "'right-harvest");
|
||||
break;
|
||||
case MouseActionDemolish:
|
||||
CLprintf(file, "'right-demolish");
|
||||
case MouseActionSpellCast:
|
||||
CLprintf(file, "'right-spell-cast");
|
||||
break;
|
||||
case MouseActionSail:
|
||||
CLprintf(file, "'right-sail");
|
||||
|
@ -872,12 +865,6 @@ local void SaveUnitType(CLFile* file, const UnitType* type, int all)
|
|||
if (type->RepairRange) {
|
||||
CLprintf(file, " 'repair-range %d\n", type->RepairRange);
|
||||
}
|
||||
if (type->DemolishRange) {
|
||||
CLprintf(file, " 'demolish-range %d\n", type->DemolishRange);
|
||||
}
|
||||
if (type->DemolishRange) {
|
||||
CLprintf(file, " 'demolish-damage %d\n", type->DemolishDamage);
|
||||
}
|
||||
if (type->CanTarget) {
|
||||
CLprintf(file, " ");
|
||||
if (type->CanTarget & CanTargetLand) {
|
||||
|
@ -1242,6 +1229,8 @@ global UnitType* NewUnitTypeSlot(char* ident)
|
|||
}
|
||||
memset(type, 0, sizeof(UnitType));
|
||||
type->Type = NumUnitTypes;
|
||||
DebugLevel3Fn("Making a new unit, called %s, branded %d\n"
|
||||
_C_ ident _C_ type->Type);
|
||||
type->Ident = ident;
|
||||
UnitTypes[NumUnitTypes++] = type;
|
||||
//
|
||||
|
|
|
@ -1265,7 +1265,7 @@ local void ConvertUnitTypeTo(Player* player, const UnitType* src, UnitType* dst)
|
|||
unit->Type = dst;
|
||||
unit->Stats = &dst->Stats[player->Player];
|
||||
// and we have new one...
|
||||
player->UnitTypesCount[dst->Type]++;
|
||||
|
||||
UpdateForNewUnit(unit, 1);
|
||||
if (dst->CanCastSpell) {
|
||||
unit->Mana = MAGIC_FOR_NEW_UNITS;
|
||||
|
|
Loading…
Add table
Reference in a new issue