418 lines
13 KiB
C++
418 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2002,2003,2004,2005 Daniel Heck
|
|
*
|
|
* 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; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* 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.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
#ifndef WORLD_HH_INCLUDED
|
|
#define WORLD_HH_INCLUDED
|
|
|
|
#include "objects.hh"
|
|
#include "util.hh"
|
|
|
|
namespace world
|
|
{
|
|
using namespace enigma;
|
|
|
|
/* -------------------- Types -------------------- */
|
|
|
|
using ecl::V2;
|
|
|
|
using std::string;
|
|
|
|
/*!
|
|
* Impulse is used to transfer force from one Object to another
|
|
* Object. Currently only Stones can be the destination of
|
|
* Impulses.
|
|
*/
|
|
struct Impulse {
|
|
// Variables
|
|
Object *sender;
|
|
GridPos dest;
|
|
Direction dir;
|
|
|
|
// Constructors
|
|
Impulse(Object *sender_, const GridPos& dest_, Direction dir_)
|
|
: sender(sender_), dest(dest_), dir(dir_)
|
|
{}
|
|
};
|
|
|
|
struct Message {
|
|
// Variables
|
|
std::string message;
|
|
enigma::Value value;
|
|
GridPos gridpos;
|
|
|
|
// Constructors
|
|
Message ();
|
|
Message (const std::string &message,
|
|
const enigma::Value &value,
|
|
GridPos gridpos = GridPos());
|
|
|
|
};
|
|
|
|
|
|
/*! The different kinds of materials objects in Enigma can be made
|
|
of. */
|
|
enum MaterialType {
|
|
MATERIAL_GLASS,
|
|
MATERIAL_METAL,
|
|
MATERIAL_STONE,
|
|
};
|
|
|
|
/*!
|
|
* This structure stores all the information that is necessary to
|
|
* handle collisions between stones and actors.
|
|
*/
|
|
struct StoneContact
|
|
{
|
|
// Variables.
|
|
Actor *actor;
|
|
GridPos stonepos;
|
|
StoneID stoneid;
|
|
StoneResponse response;
|
|
|
|
V2 contact_point; // Where do the shapes meet? (world coordinates)
|
|
V2 normal; // The surface normal at the contact point
|
|
bool is_collision; // Actor moves towards the stone, not away
|
|
bool ignore; // Ignore this contact
|
|
bool new_collision; // True if actor did not touch the stone before
|
|
bool is_contact; // if false, contact_point is closest feature
|
|
std::string sound;
|
|
|
|
// Constructor.
|
|
StoneContact (Actor *a,
|
|
GridPos stonepos,
|
|
const V2 & contact_point,
|
|
const V2 & surface_normal);
|
|
StoneContact();
|
|
};
|
|
|
|
// Which of the four faces of the stone does the actor touch?
|
|
Direction contact_face (const StoneContact &sc);
|
|
DirectionBits contact_faces (const StoneContact &sc);
|
|
|
|
/* -------------------- Force Fields -------------------- */
|
|
|
|
class ForceField {
|
|
public:
|
|
virtual ~ForceField() {}
|
|
virtual void add_force(Actor *a, V2 &force) = 0;
|
|
virtual void tick(double /*dtime*/) {}
|
|
};
|
|
|
|
class ConstantForce : public ForceField {
|
|
public:
|
|
ConstantForce(V2 f=V2()) : force(f) {}
|
|
void add_force(Actor * /*a*/, V2 &f) {
|
|
f += force;
|
|
}
|
|
void set_force (const V2 &force_) { force = force_; }
|
|
private:
|
|
V2 force;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// GLOBAL VARIABLES
|
|
//----------------------------------------------------------------------
|
|
|
|
/* The global timer for all objects that need to be notified at
|
|
regular intervals. */
|
|
extern enigma::Timer GameTimer;
|
|
|
|
/* Output a message whenever a message is being sent. */
|
|
extern bool TrackMessages;
|
|
|
|
/* A hack to implement BlackBallsStone and WhiteBallsStone. */
|
|
extern Actor *CurrentCollisionActor;
|
|
|
|
//----------------------------------------------------------------------
|
|
// FUNCTIONS
|
|
//----------------------------------------------------------------------
|
|
|
|
/* -------------------- World Management -------------------- */
|
|
|
|
void Init();
|
|
|
|
void PrepareLevel ();
|
|
|
|
/* Create a new, empty world with width `w' and height `h`. */
|
|
void Resize (int w, int h);
|
|
|
|
/* Initialize the world after loading it. Call this after loading
|
|
the world to force laser beams to be recalculated etc. */
|
|
bool InitWorld();
|
|
|
|
void Tick(double dtime);
|
|
void TickFinished ();
|
|
|
|
// Destroy all objects and the complete object repository
|
|
void Shutdown();
|
|
|
|
|
|
bool IsLevelBorder(GridPos p);
|
|
bool IsInsideLevel(GridPos p);
|
|
Object *GetObject (const GridLoc &l);
|
|
|
|
/* -------------------- Named Objects -------------------- */
|
|
|
|
void NameObject (Object *obj, const string &name);
|
|
void UnnameObject (Object *obj);
|
|
void TransferObjectName(Object *source, Object *target);
|
|
Object *GetNamedObject (const string &name);
|
|
|
|
/* -------------------- Force Fields -------------------- */
|
|
|
|
void AddForceField (ForceField *ff);
|
|
void RemoveForceField (ForceField *ff);
|
|
void SetMouseForce (V2 f);
|
|
|
|
void SetConstantForce (V2 force);
|
|
|
|
|
|
/* -------------------- Rubbers Bands -------------------- */
|
|
|
|
struct RubberBandData {
|
|
double strength;
|
|
double length;
|
|
double minlength;
|
|
RubberBandData ();
|
|
RubberBandData (const RubberBandData &);
|
|
};
|
|
|
|
struct Rubber_Band_Info {
|
|
Actor *act;
|
|
RubberBandData data;
|
|
};
|
|
typedef std::vector<Rubber_Band_Info> RBI_vector;
|
|
|
|
|
|
/*! Add a rubber band that connects an actor with either a stone
|
|
or another actor. `strength' is the force constant, and
|
|
`length' is the natural length of the elastic: if it is shorter
|
|
than `length' it will exert no force on the actor(s). */
|
|
void AddRubberBand (Actor *a, Stone *st, const RubberBandData &d);
|
|
void AddRubberBand (Actor *a, Actor *a2, const RubberBandData &d);
|
|
|
|
/*! Remove all rubber bands connected to `a'. */
|
|
bool KillRubberBands (Actor *a);
|
|
|
|
/*! Remove the rubber band between `a' and `st'. If `st' is 0,
|
|
all rubber bands connecting `a' to a stone will be cut. */
|
|
void KillRubberBand (Actor *a, Stone *st);
|
|
|
|
/*! Remove the rubber band between `a' and `a2'. If `a2' is 0,
|
|
all rubber bands connecting `a' to other actors will be cut. */
|
|
void KillRubberBand (Actor *a, Actor *a2);
|
|
|
|
/*! Remove all rubber bands attached to stone ST. */
|
|
void KillRubberBands (Stone *st);
|
|
|
|
/*! Fills given vector with basic info about rubbers attached to
|
|
given stone */
|
|
void GiveRubberBands (Stone *st, RBI_vector &rubbers);
|
|
|
|
/*! Returns true if there already is a rubber band connecting `a'
|
|
and `st'. */
|
|
bool HasRubberBand (Actor *a, Stone *st);
|
|
|
|
/* -------------------- Puzzle Stone Scrambling -------------------- */
|
|
|
|
void SetScrambleIntensity(int intensity);
|
|
void AddScramble(GridPos p, Direction d);
|
|
|
|
|
|
|
|
/* -------------------- Signals & Messages -------------------- */
|
|
|
|
void AddSignal (const GridLoc &src,
|
|
const GridLoc &dst,
|
|
const string &msg);
|
|
|
|
bool HaveSignals (Object *src);
|
|
|
|
/*! Return true if suitable signal was found. */
|
|
bool EmitSignalByIndex (Object *src, int signalidx, int value=0);
|
|
|
|
/* Signal indices start at 0 */
|
|
bool GetSignalTargetPos (Object *src, GridPos &pos, int signalidx = 0);
|
|
|
|
void BroadcastMessage (const std::string& msg, const enigma::Value& value,
|
|
GridLayerBits grids);
|
|
|
|
Value SendMessage (Object *o, const string &msg);
|
|
Value SendMessage (Object *o, const string &msg, const enigma::Value& value);
|
|
Value SendMessage (Object *o, const Message &m);
|
|
|
|
/*! This function is used by all triggers, switches etc. that
|
|
perform some particular action when activated (like opening
|
|
doors or switching lasers on and off). It interprets the
|
|
"action" and "target" attributes of `o'. */
|
|
void PerformAction (Object *o, bool onoff);
|
|
|
|
|
|
/* -------------------- Actors -------------------- */
|
|
|
|
void AddActor (Actor *a);
|
|
void AddActor (double x, double y, Actor* a);
|
|
|
|
Actor *YieldActor(Actor *a);
|
|
void KillActor (Actor *a);
|
|
|
|
void WarpActor (Actor *a, double newx, double newy, bool keep_velocity);
|
|
|
|
/*! Move `a' to its respawnpos immediately; do not run an
|
|
animation like `RespawnActor(a)' would. */
|
|
void FastRespawnActor (Actor *a, bool keep_velocity);
|
|
|
|
/*! Like FastRespawnActor but marble 'appears' by running an
|
|
animation. */
|
|
void RespawnActor (Actor *a);
|
|
|
|
/*! Find the marble of the other color (ac-whiteball <->
|
|
ac-blackball). */
|
|
Actor *FindOtherMarble (Actor *thisMarble);
|
|
|
|
/*! Searches for other marble and exchanges their positions.
|
|
Returns false if no other marble could be found. */
|
|
bool ExchangeMarbles (Actor *marble1);
|
|
|
|
void GrabActor (Actor *a);
|
|
void ReleaseActor (Actor *a);
|
|
|
|
unsigned CountActorsOfKind (ActorID id);
|
|
|
|
/*! Find all actors at most RANGE units away from CENTER. Returns
|
|
false if none were found. */
|
|
bool GetActorsInRange (ecl::V2 center, double range, std::vector<Actor*> &actors);
|
|
|
|
/*! Find all actors that are inside 'pos'. Returns false if none
|
|
were found. */
|
|
bool GetActorsInsideField (const GridPos& pos, std::vector<Actor*>& actors);
|
|
|
|
/*! Shatter all actors inside 'pos'. */
|
|
void ShatterActorsInsideField (const GridPos &pos);
|
|
|
|
|
|
/* -------------------- Field -------------------- */
|
|
|
|
struct Field {
|
|
// Variables
|
|
Floor *floor;
|
|
Item *item;
|
|
Stone *stone;
|
|
|
|
// Constructor and Destructor
|
|
Field();
|
|
~Field();
|
|
};
|
|
|
|
const Field *GetField (GridPos p);
|
|
|
|
/* -------------------- Stones -------------------- */
|
|
|
|
void SetStone(GridPos p, Stone* st);
|
|
void ReplaceStone(GridPos p, Stone *st);
|
|
Stone *GetStone(GridPos p);
|
|
Stone *YieldStone(GridPos p);
|
|
void KillStone(GridPos p);
|
|
|
|
void MoveStone(GridPos oldPos, GridPos newPos);
|
|
|
|
/* -------------------- Items -------------------- */
|
|
|
|
void SetItem (GridPos p, Item* it);
|
|
void SetItem (GridPos p, ItemID id);
|
|
Item *GetItem (GridPos p);
|
|
Item *YieldItem (GridPos p);
|
|
void KillItem (GridPos p);
|
|
|
|
/* -------------------- Floors -------------------- */
|
|
|
|
void SetFloor (GridPos p, Floor* st);
|
|
Floor *GetFloor (GridPos p);
|
|
void KillFloor (GridPos p);
|
|
|
|
/* -------------------- Impulses -------------------- */
|
|
|
|
void addDelayedImpulse(const Impulse& impulse, double delay,
|
|
const Stone *estimated_receiver);
|
|
|
|
/*! Revoke all delayed impulses with TARGET as sender or receiver. */
|
|
void revokeDelayedImpulses(const Stone *target);
|
|
|
|
|
|
/* -------------------- Explosions -------------------- */
|
|
|
|
enum ExplosionType {
|
|
EXPLOSION_DYNAMITE,
|
|
EXPLOSION_BLACKBOMB,
|
|
EXPLOSION_WHITEBOMB,
|
|
EXPLOSION_BOMBSTONE,
|
|
EXPLOSION_SPITTER,
|
|
};
|
|
void SendExplosionEffect (GridPos p, ExplosionType type);
|
|
|
|
/* -------------------- Sound Events and Damping -------------------- */
|
|
|
|
float getVolume(const char *name, Object *obj, float def_volume = 1.0);
|
|
|
|
/* -------------------- Creation/Definition of objects -------------------- */
|
|
|
|
Object *MakeObject (const char *kind);
|
|
Floor *MakeFloor (const char *kind);
|
|
Stone *MakeStone (const char *kind);
|
|
Stone *MakeStone (StoneID id);
|
|
Actor *MakeActor (const char *kind);
|
|
Actor *MakeActor (ActorID id);
|
|
|
|
void DisposeObject(Object *o);
|
|
|
|
void DefineSimpleStone (const string &kind, const string &sound,
|
|
int hollow, int glass);
|
|
|
|
void DefineSimpleStoneMovable (const string &kind, const string &sound,
|
|
int glass);
|
|
|
|
void DefineSimpleFloor(const string &kind, double friction,
|
|
double mousefactor, bool burnable,
|
|
const string &firetransform);
|
|
|
|
/* Register a new object. */
|
|
void Register (Object *obj);
|
|
void Register (const string &kind, Object *obj);
|
|
void Register (const string &kind, Floor *obj);
|
|
void Register (const string &kind, Stone *obj);
|
|
void RegisterStone (Stone *st);
|
|
void RegisterActor (Actor *ac);
|
|
|
|
|
|
|
|
void Register (const string &kind, Item *obj);
|
|
void RegisterItem (Item *it);
|
|
Item *MakeItem (const char *kind);
|
|
Item *MakeItem (ItemID id);
|
|
|
|
/* Shutdown object repository */
|
|
void Repos_Shutdown();
|
|
|
|
Object *GetObjectTemplate(const string &kind);
|
|
|
|
/* Print information about all registered objects to stdout. */
|
|
void DumpObjectInfo();
|
|
}
|
|
|
|
#endif
|