From 449cc186d5b8117d74ba22d6173497d00939f5f1 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 28 Apr 2012 17:53:17 +0200 Subject: Source files split into modules --- src/object/README.txt | 3 + src/object/auto/auto.cpp | 461 +++ src/object/auto/auto.h | 114 + src/object/auto/autobase.cpp | 1459 +++++++ src/object/auto/autobase.h | 122 + src/object/auto/autoconvert.cpp | 546 +++ src/object/auto/autoconvert.h | 82 + src/object/auto/autoderrick.cpp | 605 +++ src/object/auto/autoderrick.h | 84 + src/object/auto/autodestroyer.cpp | 397 ++ src/object/auto/autodestroyer.h | 76 + src/object/auto/autoegg.cpp | 375 ++ src/object/auto/autoegg.h | 83 + src/object/auto/autoenergy.cpp | 665 +++ src/object/auto/autoenergy.h | 83 + src/object/auto/autofactory.cpp | 961 +++++ src/object/auto/autofactory.h | 85 + src/object/auto/autoflag.cpp | 178 + src/object/auto/autoflag.h | 58 + src/object/auto/autohuston.cpp | 315 ++ src/object/auto/autohuston.h | 77 + src/object/auto/autoinfo.cpp | 537 +++ src/object/auto/autoinfo.h | 80 + src/object/auto/autojostle.cpp | 167 + src/object/auto/autojostle.h | 60 + src/object/auto/autokid.cpp | 222 + src/object/auto/autokid.h | 59 + src/object/auto/autolabo.cpp | 629 +++ src/object/auto/autolabo.h | 87 + src/object/auto/automush.cpp | 362 ++ src/object/auto/automush.h | 73 + src/object/auto/autonest.cpp | 291 ++ src/object/auto/autonest.h | 73 + src/object/auto/autonuclear.cpp | 504 +++ src/object/auto/autonuclear.h | 80 + src/object/auto/autopara.cpp | 347 ++ src/object/auto/autopara.h | 77 + src/object/auto/autoportico.cpp | 446 ++ src/object/auto/autoportico.h | 81 + src/object/auto/autoradar.cpp | 326 ++ src/object/auto/autoradar.h | 76 + src/object/auto/autorepair.cpp | 362 ++ src/object/auto/autorepair.h | 76 + src/object/auto/autoresearch.cpp | 627 +++ src/object/auto/autoresearch.h | 82 + src/object/auto/autoroot.cpp | 135 + src/object/auto/autoroot.h | 56 + src/object/auto/autosafe.cpp | 636 +++ src/object/auto/autosafe.h | 86 + src/object/auto/autostation.cpp | 387 ++ src/object/auto/autostation.h | 68 + src/object/auto/autotower.cpp | 561 +++ src/object/auto/autotower.h | 86 + src/object/brain.cpp | 3000 ++++++++++++++ src/object/brain.h | 220 + src/object/motion/motion.cpp | 257 ++ src/object/motion/motion.h | 94 + src/object/motion/motionant.cpp | 901 +++++ src/object/motion/motionant.h | 80 + src/object/motion/motionbee.cpp | 663 +++ src/object/motion/motionbee.h | 73 + src/object/motion/motionhuman.cpp | 1799 +++++++++ src/object/motion/motionhuman.h | 102 + src/object/motion/motionmother.cpp | 543 +++ src/object/motion/motionmother.h | 67 + src/object/motion/motionspider.cpp | 789 ++++ src/object/motion/motionspider.h | 78 + src/object/motion/motiontoto.cpp | 886 ++++ src/object/motion/motiontoto.h | 81 + src/object/motion/motionvehicle.cpp | 2091 ++++++++++ src/object/motion/motionvehicle.h | 82 + src/object/motion/motionworm.cpp | 380 ++ src/object/motion/motionworm.h | 75 + src/object/object.cpp | 7607 +++++++++++++++++++++++++++++++++++ src/object/object.h | 781 ++++ src/object/robotmain.cpp | 7031 ++++++++++++++++++++++++++++++++ src/object/robotmain.h | 463 +++ src/object/task/task.cpp | 109 + src/object/task/task.h | 89 + src/object/task/taskadvance.cpp | 159 + src/object/task/taskadvance.h | 59 + src/object/task/taskbuild.cpp | 822 ++++ src/object/task/taskbuild.h | 93 + src/object/task/taskfire.cpp | 398 ++ src/object/task/taskfire.h | 61 + src/object/task/taskfireant.cpp | 227 ++ src/object/task/taskfireant.h | 72 + src/object/task/taskflag.cpp | 321 ++ src/object/task/taskflag.h | 66 + src/object/task/taskgoto.cpp | 2352 +++++++++++ src/object/task/taskgoto.h | 167 + src/object/task/taskgungoal.cpp | 161 + src/object/task/taskgungoal.h | 57 + src/object/task/taskinfo.cpp | 233 ++ src/object/task/taskinfo.h | 57 + src/object/task/taskmanager.cpp | 291 ++ src/object/task/taskmanager.h | 77 + src/object/task/taskmanip.cpp | 1398 +++++++ src/object/task/taskmanip.h | 109 + src/object/task/taskpen.cpp | 304 ++ src/object/task/taskpen.h | 77 + src/object/task/taskrecover.cpp | 431 ++ src/object/task/taskrecover.h | 75 + src/object/task/taskreset.cpp | 345 ++ src/object/task/taskreset.h | 73 + src/object/task/tasksearch.cpp | 334 ++ src/object/task/tasksearch.h | 79 + src/object/task/taskshield.cpp | 573 +++ src/object/task/taskshield.h | 94 + src/object/task/taskspiderexplo.cpp | 124 + src/object/task/taskspiderexplo.h | 53 + src/object/task/tasktake.cpp | 612 +++ src/object/task/tasktake.h | 85 + src/object/task/taskterraform.cpp | 429 ++ src/object/task/taskterraform.h | 72 + src/object/task/taskturn.cpp | 147 + src/object/task/taskturn.h | 55 + src/object/task/taskwait.cpp | 89 + src/object/task/taskwait.h | 53 + 119 files changed, 54193 insertions(+) create mode 100644 src/object/README.txt create mode 100644 src/object/auto/auto.cpp create mode 100644 src/object/auto/auto.h create mode 100644 src/object/auto/autobase.cpp create mode 100644 src/object/auto/autobase.h create mode 100644 src/object/auto/autoconvert.cpp create mode 100644 src/object/auto/autoconvert.h create mode 100644 src/object/auto/autoderrick.cpp create mode 100644 src/object/auto/autoderrick.h create mode 100644 src/object/auto/autodestroyer.cpp create mode 100644 src/object/auto/autodestroyer.h create mode 100644 src/object/auto/autoegg.cpp create mode 100644 src/object/auto/autoegg.h create mode 100644 src/object/auto/autoenergy.cpp create mode 100644 src/object/auto/autoenergy.h create mode 100644 src/object/auto/autofactory.cpp create mode 100644 src/object/auto/autofactory.h create mode 100644 src/object/auto/autoflag.cpp create mode 100644 src/object/auto/autoflag.h create mode 100644 src/object/auto/autohuston.cpp create mode 100644 src/object/auto/autohuston.h create mode 100644 src/object/auto/autoinfo.cpp create mode 100644 src/object/auto/autoinfo.h create mode 100644 src/object/auto/autojostle.cpp create mode 100644 src/object/auto/autojostle.h create mode 100644 src/object/auto/autokid.cpp create mode 100644 src/object/auto/autokid.h create mode 100644 src/object/auto/autolabo.cpp create mode 100644 src/object/auto/autolabo.h create mode 100644 src/object/auto/automush.cpp create mode 100644 src/object/auto/automush.h create mode 100644 src/object/auto/autonest.cpp create mode 100644 src/object/auto/autonest.h create mode 100644 src/object/auto/autonuclear.cpp create mode 100644 src/object/auto/autonuclear.h create mode 100644 src/object/auto/autopara.cpp create mode 100644 src/object/auto/autopara.h create mode 100644 src/object/auto/autoportico.cpp create mode 100644 src/object/auto/autoportico.h create mode 100644 src/object/auto/autoradar.cpp create mode 100644 src/object/auto/autoradar.h create mode 100644 src/object/auto/autorepair.cpp create mode 100644 src/object/auto/autorepair.h create mode 100644 src/object/auto/autoresearch.cpp create mode 100644 src/object/auto/autoresearch.h create mode 100644 src/object/auto/autoroot.cpp create mode 100644 src/object/auto/autoroot.h create mode 100644 src/object/auto/autosafe.cpp create mode 100644 src/object/auto/autosafe.h create mode 100644 src/object/auto/autostation.cpp create mode 100644 src/object/auto/autostation.h create mode 100644 src/object/auto/autotower.cpp create mode 100644 src/object/auto/autotower.h create mode 100644 src/object/brain.cpp create mode 100644 src/object/brain.h create mode 100644 src/object/motion/motion.cpp create mode 100644 src/object/motion/motion.h create mode 100644 src/object/motion/motionant.cpp create mode 100644 src/object/motion/motionant.h create mode 100644 src/object/motion/motionbee.cpp create mode 100644 src/object/motion/motionbee.h create mode 100644 src/object/motion/motionhuman.cpp create mode 100644 src/object/motion/motionhuman.h create mode 100644 src/object/motion/motionmother.cpp create mode 100644 src/object/motion/motionmother.h create mode 100644 src/object/motion/motionspider.cpp create mode 100644 src/object/motion/motionspider.h create mode 100644 src/object/motion/motiontoto.cpp create mode 100644 src/object/motion/motiontoto.h create mode 100644 src/object/motion/motionvehicle.cpp create mode 100644 src/object/motion/motionvehicle.h create mode 100644 src/object/motion/motionworm.cpp create mode 100644 src/object/motion/motionworm.h create mode 100644 src/object/object.cpp create mode 100644 src/object/object.h create mode 100644 src/object/robotmain.cpp create mode 100644 src/object/robotmain.h create mode 100644 src/object/task/task.cpp create mode 100644 src/object/task/task.h create mode 100644 src/object/task/taskadvance.cpp create mode 100644 src/object/task/taskadvance.h create mode 100644 src/object/task/taskbuild.cpp create mode 100644 src/object/task/taskbuild.h create mode 100644 src/object/task/taskfire.cpp create mode 100644 src/object/task/taskfire.h create mode 100644 src/object/task/taskfireant.cpp create mode 100644 src/object/task/taskfireant.h create mode 100644 src/object/task/taskflag.cpp create mode 100644 src/object/task/taskflag.h create mode 100644 src/object/task/taskgoto.cpp create mode 100644 src/object/task/taskgoto.h create mode 100644 src/object/task/taskgungoal.cpp create mode 100644 src/object/task/taskgungoal.h create mode 100644 src/object/task/taskinfo.cpp create mode 100644 src/object/task/taskinfo.h create mode 100644 src/object/task/taskmanager.cpp create mode 100644 src/object/task/taskmanager.h create mode 100644 src/object/task/taskmanip.cpp create mode 100644 src/object/task/taskmanip.h create mode 100644 src/object/task/taskpen.cpp create mode 100644 src/object/task/taskpen.h create mode 100644 src/object/task/taskrecover.cpp create mode 100644 src/object/task/taskrecover.h create mode 100644 src/object/task/taskreset.cpp create mode 100644 src/object/task/taskreset.h create mode 100644 src/object/task/tasksearch.cpp create mode 100644 src/object/task/tasksearch.h create mode 100644 src/object/task/taskshield.cpp create mode 100644 src/object/task/taskshield.h create mode 100644 src/object/task/taskspiderexplo.cpp create mode 100644 src/object/task/taskspiderexplo.h create mode 100644 src/object/task/tasktake.cpp create mode 100644 src/object/task/tasktake.h create mode 100644 src/object/task/taskterraform.cpp create mode 100644 src/object/task/taskterraform.h create mode 100644 src/object/task/taskturn.cpp create mode 100644 src/object/task/taskturn.h create mode 100644 src/object/task/taskwait.cpp create mode 100644 src/object/task/taskwait.h (limited to 'src/object') diff --git a/src/object/README.txt b/src/object/README.txt new file mode 100644 index 0000000..f4c25d0 --- /dev/null +++ b/src/object/README.txt @@ -0,0 +1,3 @@ +src/object + +Contains modules of robots and buildings. diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp new file mode 100644 index 0000000..9711423 --- /dev/null +++ b/src/object/auto/auto.cpp @@ -0,0 +1,461 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "water.h" +#include "cloud.h" +#include "planet.h" +#include "blitz.h" +#include "camera.h" +#include "object.h" +#include "modfile.h" +#include "interface.h" +#include "button.h" +#include "list.h" +#include "label.h" +#include "gauge.h" +#include "window.h" +#include "robotmain.h" +#include "displaytext.h" +#include "sound.h" +#include "cmdtoken.h" +#include "auto.h" + + + + +// Object's constructor. + +CAuto::CAuto(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_AUTO, this, 100); + + m_object = object; + m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT); + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD); + m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET); + m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + + m_type = m_object->RetType(); + m_time = 0.0f; + m_lastUpdateTime = 0.0f; + m_bMotor = FALSE; + m_progressTime = 0.0f; + m_progressTotal = 1.0f; + + Init(); +} + +// Object's destructor. + +CAuto::~CAuto() +{ + m_iMan->DeleteInstance(CLASS_AUTO, this); +} + + +// Destroys the object. + +void CAuto::DeleteObject(BOOL bAll) +{ +} + + +// Initialize the object. + +void CAuto::Init() +{ + m_bBusy = FALSE; +} + +// Starts the object. + +void CAuto::Start(int param) +{ +} + + +// Give a type. + +BOOL CAuto::SetType(ObjectType type) +{ + return FALSE; +} + +// Gives a value. + +BOOL CAuto::SetValue(int rank, float value) +{ + return FALSE; +} + +// Gives the string. + +BOOL CAuto::SetString(char *string) +{ + return FALSE; +} + + +// Management of an event. + +BOOL CAuto::EventProcess(const Event &event) +{ + if ( event.event == EVENT_FRAME && + !m_engine->RetPause() ) + { + m_time += event.rTime; + UpdateInterface(event.rTime); + } + + if ( !m_object->RetSelect() ) // robot not selected? + { + return TRUE; + } + + return TRUE; +} + +// Indicates whether the controller has finished its activity. + +Error CAuto::IsEnded() +{ + return ERR_CONTINUE; +} + +// Stops the controller + +BOOL CAuto::Abort() +{ + return FALSE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAuto::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + char name[100]; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + pw->Flush(); // destroys the window buttons + m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window + } + + if ( !bSelect ) return TRUE; + + pos.x = 0.0f; + pos.y = 0.0f; + dim.x = 540.0f/640.0f; +//? dim.y = 70.0f/480.0f; + dim.y = 86.0f/480.0f; + m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0); + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + m_object->GetTooltipName(name); + pos.x = 0.0f; + pos.y = 64.0f/480.0f; + ddim.x = 540.0f/640.0f; + ddim.y = 16.0f/480.0f; + pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name); + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.6f; + ddim.x = 160.0f/640.0f; + ddim.y = 26.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS); + + if ( m_type != OBJECT_BASE && + m_type != OBJECT_SAFE && + m_type != OBJECT_HUSTON ) + { + pos.x = ox+sx*2.1f; + pos.y = oy+sy*0; + ddim.x = dim.x*0.6f; + ddim.y = dim.y*0.6f; + pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE); + } + +#if 0 + pos.x = ox+sx*12.4f; + pos.y = oy+sy*1; + pw->CreateButton(pos, dim, 63, EVENT_OBJECT_BHELP); + + pos.x = ox+sx*12.4f; + pos.y = oy+sy*0; + pw->CreateButton(pos, dim, 19, EVENT_OBJECT_HELP); + + if ( m_main->RetSceneSoluce() ) + { + pos.x = ox+sx*13.4f; + pos.y = oy+sy*1; + pw->CreateButton(pos, dim, 20, EVENT_OBJECT_SOLUCE); + } + + pos.x = ox+sx*13.4f; + pos.y = oy+sy*0; + pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT); +#else + pos.x = ox+sx*12.3f; + pos.y = oy+sy*-0.1f; + ddim.x = dim.x*1.0f; + ddim.y = dim.y*2.1f; + pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue background + + pos.x = ox+sx*12.3f; + pos.y = oy+sy*1; + pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom + + pos.x = ox+sx*12.4f; + pos.y = oy+sy*0.5f; + ddim.x = dim.x*0.8f; + ddim.y = dim.y*0.5f; + pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP); + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP); + + pos.x = ox+sx*13.4f; + pos.y = oy+sy*0; + pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT); +#endif + + pos.x = ox+sx*14.9f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD); + + UpdateInterface(); + m_lastUpdateTime = 0.0f; + UpdateInterface(0.0f); + + return TRUE; +} + +// Change the state of a button interface. + +void CAuto::CheckInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_CHECK, bState); +} + +// Change the state of a button interface. + +void CAuto::EnableInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_ENABLE, bState); +} + +// Change the state of a button interface. + +void CAuto::VisibleInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_VISIBLE, bState); +} + +// Change the state of a button interface. + +void CAuto::DeadInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_DEAD, !bState); +} + +// Change the state of a button interface. + +void CAuto::UpdateInterface() +{ + CWindow* pw; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy); +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAuto::UpdateInterface(float rTime) +{ + CWindow* pw; + CGauge* pg; + + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD); + if ( pg != 0 ) + { + pg->SetLevel(m_object->RetShield()); + } + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GPROGRESS); + if ( pg != 0 ) + { + pg->SetLevel(m_progressTime); + } +} + + +// Returns an error due the state of the automation. + +Error CAuto::RetError() +{ + return ERR_OK; +} + + +// Management of the occupation. + +BOOL CAuto::RetBusy() +{ + return m_bBusy; +} + +void CAuto::SetBusy(BOOL bBusy) +{ + m_bBusy = bBusy; +} + +void CAuto::InitProgressTotal(float total) +{ + m_progressTime = 0.0f; + m_progressTotal = total; +} + +void CAuto::EventProgress(float rTime) +{ + m_progressTime += rTime/m_progressTotal; +} + + +// Engine management. + +BOOL CAuto::RetMotor() +{ + return m_bMotor; +} + +void CAuto::SetMotor(BOOL bMotor) +{ + m_bMotor = bMotor; +} + + +// Saves all parameters of the controller. + +BOOL CAuto::Write(char *line) +{ + char name[100]; + + sprintf(name, " aType=%d", m_type); + strcat(line, name); + + sprintf(name, " aBusy=%d", m_bBusy); + strcat(line, name); + + sprintf(name, " aTime=%.2f", m_time); + strcat(line, name); + + sprintf(name, " aProgressTime=%.2f", m_progressTime); + strcat(line, name); + + sprintf(name, " aProgressTotal=%.2f", m_progressTotal); + strcat(line, name); + + return FALSE; +} + +// Return all settings to the controller. + +BOOL CAuto::Read(char *line) +{ + m_type = (ObjectType)OpInt(line, "aType", OBJECT_NULL); + m_bBusy = OpInt(line, "aBusy", 0); + m_time = OpFloat(line, "aTime", 0.0f); + m_progressTime = OpFloat(line, "aProgressTime", 0.0f); + m_progressTotal = OpFloat(line, "aProgressTotal", 0.0f); + + return FALSE; +} + diff --git a/src/object/auto/auto.h b/src/object/auto/auto.h new file mode 100644 index 0000000..4cc9389 --- /dev/null +++ b/src/object/auto/auto.h @@ -0,0 +1,114 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// auto.h + +#ifndef _AUTO_H_ +#define _AUTO_H_ + + +#include "object.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CLight; +class CTerrain; +class CWater; +class CCloud; +class CPlanet; +class CBlitz; +class CCamera; +class CObject; +class CInterface; +class CRobotMain; +class CDisplayText; +class CWindow; +class CSound; + + + + +class CAuto +{ +public: + CAuto(CInstanceManager* iMan, CObject* object); + ~CAuto(); + + virtual void DeleteObject(BOOL bAll=FALSE); + + virtual void Init(); + virtual void Start(int param); + virtual BOOL EventProcess(const Event &event); + virtual Error IsEnded(); + virtual BOOL Abort(); + + virtual BOOL SetType(ObjectType type); + virtual BOOL SetValue(int rank, float value); + virtual BOOL SetString(char *string); + + virtual BOOL CreateInterface(BOOL bSelect); + virtual Error RetError(); + + virtual BOOL RetBusy(); + virtual void SetBusy(BOOL bBuse); + virtual void InitProgressTotal(float total); + virtual void EventProgress(float rTime); + + virtual BOOL RetMotor(); + virtual void SetMotor(BOOL bMotor); + + virtual BOOL Write(char *line); + virtual BOOL Read(char *line); + +protected: + void CheckInterface(CWindow *pw, EventMsg event, BOOL bState); + void EnableInterface(CWindow *pw, EventMsg event, BOOL bState); + void VisibleInterface(CWindow *pw, EventMsg event, BOOL bState); + void DeadInterface(CWindow *pw, EventMsg event, BOOL bState); + void UpdateInterface(); + void UpdateInterface(float rTime); + +protected: + CInstanceManager* m_iMan; + CEvent* m_event; + CD3DEngine* m_engine; + CParticule* m_particule; + CLight* m_light; + CTerrain* m_terrain; + CWater* m_water; + CCloud * m_cloud; + CPlanet * m_planet; + CBlitz* m_blitz; + CCamera* m_camera; + CInterface* m_interface; + CRobotMain* m_main; + CDisplayText* m_displayText; + CObject* m_object; + CSound* m_sound; + + ObjectType m_type; + BOOL m_bBusy; + BOOL m_bMotor; + float m_time; + float m_lastUpdateTime; + float m_progressTime; + float m_progressTotal; +}; + + +#endif //_AUTO_H_ diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp new file mode 100644 index 0000000..fada8d5 --- /dev/null +++ b/src/object/auto/autobase.cpp @@ -0,0 +1,1459 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "language.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "cloud.h" +#include "planet.h" +#include "blitz.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "displaytext.h" +#include "robotmain.h" +#include "sound.h" +#include "auto.h" +#include "autobase.h" + + + +#define BASE_LAND_TIME 7.5f // hard landing +#define BASE_TAKO_TIME 10.0f // hard landing +#define BASE_DOOR_TIME 6.0f // time opening / closing +#define BASE_DOOR_TIME2 2.0f // time opening / closing suppl. +#define BASE_PORTICO_TIME_MOVE 16.0f // gate advance time +#define BASE_PORTICO_TIME_DOWN 4.0f // gate length down +#define BASE_PORTICO_TIME_OPEN 4.0f // gate opening duration +#define BASE_TRANSIT_TIME 15.0f // transit duration + + + + +// Object's constructor. + +CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_fogStart = m_engine->RetFogStart(); + m_deepView = m_engine->RetDeepView(); + Init(); + m_phase = ABP_WAIT; + m_soundChannel = -1; +} + +// Object's destructor. + +CAutoBase::~CAutoBase() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoBase::DeleteObject(BOOL bAll) +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoBase::Init() +{ + m_bOpen = FALSE; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_lastMotorParticule = 0.0f; + + m_pos = m_object->RetPosition(0); + m_lastPos = m_pos; + + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; +} + + +// Start the object. + +void CAutoBase::Start(int param) +{ + m_phase = ABP_START; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + m_param = param; +} + + +// Management of an event. + +BOOL CAutoBase::EventProcess(const Event &event) +{ + D3DMATRIX* mat; + Event newEvent; + CObject* pObj; + D3DVECTOR pos, speed, vibCir, iPos; + FPOINT dim, p; + Error err; + float angle, dist, time, h, len, vSpeed; + int i, max; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + +begin: + iPos = m_object->RetPosition(0); + + if ( m_phase == ABP_START ) + { + if ( m_param != PARAM_STOP && // not placed on the ground? + m_param != PARAM_FIXSCENE ) + { + FreezeCargo(TRUE); // freeze whole cargo + } + + if ( m_param == PARAM_STOP ) // raises the ground? + { + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f); + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f)); + } + + pObj = m_main->RetSelectObject(); + m_main->SelectObject(pObj); + m_camera->SetObject(pObj); + if ( pObj == 0 ) + { + m_camera->SetType(CAMERA_BACK); + } + else + { + m_camera->SetType(pObj->RetCameraType()); + m_camera->SetDist(pObj->RetCameraDist()); + } + + m_main->StartMusic(); + } + + if ( m_param == PARAM_FIXSCENE ) // raises the ground? + { + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f); + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f)); + } + } + + if ( m_param == PARAM_LANDING ) // Landing? + { + m_phase = ABP_LAND; + m_progress = 0.0f; + m_speed = 1.0f/BASE_LAND_TIME; + + m_main->SetMovieLock(TRUE); // blocks everything until the end of the landing + m_bMotor = TRUE; // lights the jet engine + + m_camera->SetType(CAMERA_SCRIPT); + + pos = m_pos; + pos.x -= 150.0f; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + m_camera->SetScriptEye(pos); + m_posSound = pos; + + pos = m_object->RetPosition(0); + pos.y += 300.0f+50.0f; + m_camera->SetScriptLookat(pos); + + m_camera->FixCamera(); + m_engine->SetFocus(2.0f); + + m_engine->SetFogStart(0.9f); + + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.3f, 2.0f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, BASE_LAND_TIME, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 2.0f, SOPER_STOP); + } + + m_main->StartMusic(); + } + + if ( m_param == PARAM_PORTICO ) // gate on the porch? + { + pos = m_object->RetPosition(0); + m_finalPos = pos; + pos.z += BASE_PORTICO_TIME_MOVE*5.0f; // back + pos.y += 10.0f; // rises (the gate) + m_object->SetPosition(0, pos); + MoveCargo(); // all cargo moves + + m_phase = ABP_PORTICO_MOVE; + m_progress = 0.0f; + m_speed = 1.0f/BASE_PORTICO_TIME_MOVE; + + m_main->StartMusic(); + } + + if ( m_param == PARAM_TRANSIT1 || + m_param == PARAM_TRANSIT2 || + m_param == PARAM_TRANSIT3 ) // transit in space? + { + m_phase = ABP_TRANSIT_MOVE; + m_progress = 0.0f; + m_speed = 1.0f/BASE_TRANSIT_TIME; + + m_object->SetAngleZ(0, -PI/2.0f); + pos = m_object->RetPosition(0); + pos.y += 10000.0f; // in space + m_finalPos = pos; + m_object->SetPosition(0, pos); + + m_main->SetMovieLock(TRUE); // blocks everything until the end of the landing + m_bMotor = TRUE; // lights the jet engine + + m_camera->SetType(CAMERA_SCRIPT); + pos.x += 1000.0f; + pos.z -= 60.0f; + pos.y += 80.0f; + m_camera->SetScriptEye(pos); + m_posSound = pos; + m_camera->FixCamera(); + m_engine->SetFocus(1.0f); + + BeginTransit(); + + mat = m_object->RetWorldMatrix(0); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 10.0f; + dim.y = dim.x; + pos = D3DVECTOR(42.0f, -2.0f, 17.0f); + pos = Transform(*mat, pos); + m_partiChannel[0] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(17.0f, -2.0f, 42.0f); + pos = Transform(*mat, pos); + m_partiChannel[1] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(42.0f, -2.0f, -17.0f); + pos = Transform(*mat, pos); + m_partiChannel[2] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(17.0f, -2.0f, -42.0f); + pos = Transform(*mat, pos); + m_partiChannel[3] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(-42.0f, -2.0f, 17.0f); + pos = Transform(*mat, pos); + m_partiChannel[4] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(-17.0f, -2.0f, 42.0f); + pos = Transform(*mat, pos); + m_partiChannel[5] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(-42.0f, -2.0f, -17.0f); + pos = Transform(*mat, pos); + m_partiChannel[6] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + pos = D3DVECTOR(-17.0f, -2.0f, -42.0f); + pos = Transform(*mat, pos); + m_partiChannel[7] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f); + + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 1.2f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, BASE_TRANSIT_TIME*0.55f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.8f, BASE_TRANSIT_TIME*0.45f, SOPER_STOP); + } + } + } + + if ( event.event == EVENT_UPDINTERFACE ) + { + if ( m_object->RetSelect() ) CreateInterface(TRUE); + } + + if ( event.event == EVENT_OBJECT_BTAKEOFF ) + { + err = CheckCloseDoor(); + if ( err != ERR_OK ) + { + m_displayText->DisplayError(err, m_object); + return FALSE; + } + + err = m_main->CheckEndMission(FALSE); + if ( err != ERR_OK ) + { + m_displayText->DisplayError(err, m_object); + return FALSE; + } + + FreezeCargo(TRUE); // freeze whole cargo + m_main->SetMovieLock(TRUE); // blocks everything until the end + m_main->DeselectAll(); + + m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE); + m_event->AddEvent(newEvent); + + m_camera->SetType(CAMERA_SCRIPT); + + pos = m_pos; + pos.x -= 110.0f; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + m_camera->SetScriptEye(pos); + m_posSound = pos; + + pos = m_object->RetPosition(0); + pos.y += 50.0f; + m_camera->SetScriptLookat(pos); + + m_engine->SetFocus(1.0f); + + m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP); + + m_phase = ABP_CLOSE2; + m_progress = 0.0f; + m_speed = 1.0f/BASE_DOOR_TIME2; + return TRUE; + } + + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_phase == ABP_WAIT ) return TRUE; + + m_progress += event.rTime*m_speed; + + if ( m_phase == ABP_LAND ) + { + if ( m_progress < 1.0f ) + { + pos = m_pos; + pos.y += powf(1.0f-m_progress, 2.0f)*300.0f; + m_object->SetPosition(0, pos); + MoveCargo(); // all cargo moves + + vibCir.z = sinf(m_time*PI* 2.01f)*(PI/150.0f)+ + sinf(m_time*PI* 2.51f)*(PI/200.0f)+ + sinf(m_time*PI*19.01f)*(PI/400.0f); + vibCir.x = sinf(m_time*PI* 2.03f)*(PI/150.0f)+ + sinf(m_time*PI* 2.52f)*(PI/200.0f)+ + sinf(m_time*PI*19.53f)*(PI/400.0f); + vibCir.y = 0.0f; + vibCir *= Min(1.0f, (1.0f-m_progress)*3.0f); + m_object->SetCirVibration(vibCir); + + pos = m_pos; + pos.x -= 150.0f; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + m_camera->SetScriptEye(pos); + + pos = m_object->RetPosition(0); + pos.y += 50.0f; + m_camera->SetScriptLookat(pos); + + m_engine->SetFocus(1.0f+(1.0f-m_progress)); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + // Dust thrown to the ground. + pos = m_pos; + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + angle = Rand()*(PI*2.0f); + dist = m_progress*50.0f; + p = RotatePoint(angle, dist); + speed.x = p.x; + speed.z = p.y; + speed.y = 0.0f; + dim.x = (Rand()*15.0f+15.0f)*m_progress; + dim.y = dim.x; + if ( dim.x >= 1.0f ) + { + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f); + } + + // Particles are ejected from the jet engine. + pos = m_object->RetPosition(0); + pos.y += 6.0f; + h = m_terrain->RetFloorHeight(pos)/300.0f; + speed.x = (Rand()-0.5f)*(80.0f-50.0f*h); + speed.z = (Rand()-0.5f)*(80.0f-50.0f*h); + speed.y = -(Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f); + dim.x = Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f); + + // Black smoke from the jet engine. + if ( m_progress > 0.8f ) + { + pos = m_pos; + pos.x += (Rand()-0.5f)*8.0f; + pos.z += (Rand()-0.5f)*8.0f; + pos.y += 3.0f; + speed.x = (Rand()-0.5f)*8.0f; + speed.z = (Rand()-0.5f)*8.0f; + speed.y = 0.0f; + dim.x = Rand()*4.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f); + } + } + } + else + { + m_bMotor = FALSE; // put out the reactor + + m_object->SetPosition(0, m_pos); // setting down + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + MoveCargo(); // all cargo moves + + // Impact with the ground. + max = (int)(50.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f); + } + +//? m_camera->StartEffect(CE_CRASH, m_pos, 1.0f); + m_camera->StartEffect(CE_EXPLO, m_pos, 2.0f); + m_engine->SetFocus(1.0f); + m_sound->Play(SOUND_BOUM, m_posSound, 0.6f, 0.5f); + + m_phase = ABP_OPENWAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == ABP_OPENWAIT ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + // Black smoke from the reactor. + pos = m_pos; + pos.x += (Rand()-0.5f)*8.0f; + pos.z += (Rand()-0.5f)*8.0f; + pos.y += 3.0f; + speed.x = (Rand()-0.5f)*8.0f; + speed.z = (Rand()-0.5f)*8.0f; + speed.y = 0.0f; + dim.x = Rand()*4.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f); + } + } + else + { + m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP); + + m_phase = ABP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/BASE_DOOR_TIME; + } + } + + if ( m_phase == ABP_OPEN ) + { + if ( m_progress < 1.0f ) + { + angle = -m_progress*124.0f*PI/180.0f; + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f+angle); + } + + if ( m_param != PARAM_PORTICO ) + { + angle = m_progress*PI*2.0f; + p = RotatePoint(angle, -150.0f); + pos = m_pos; + pos.x += p.x; + pos.z += p.y; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + pos.y += m_progress*40.0f; + m_camera->SetScriptEye(pos); + + m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress); + } + } + else + { + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f); + } + + // Clash the doors with the ground. + max = (int)(20.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f); + } + + m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP); + + m_phase = ABP_OPEN2; + m_progress = 0.0f; + m_speed = 1.0f/BASE_DOOR_TIME2; + } + } + + if ( m_phase == ABP_OPEN2 ) + { + if ( m_progress < 1.0f ) + { + len = 7.0f-m_progress*(7.0f+11.5f); + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, len)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, -len)); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f*m_progress); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f*m_progress); + } + + if ( m_param != PARAM_PORTICO ) + { + angle = m_progress*PI/2.0f; + p = RotatePoint(angle, -150.0f); + pos = m_pos; + pos.x += p.x; + pos.z += p.y; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + pos.y += m_progress*40.0f; + m_camera->SetScriptEye(pos); + + m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress); + } + } + else + { + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f)); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f); + } + + m_phase = ABP_LDWAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ABP_LDWAIT ) + { + if ( m_progress >= 1.0f ) + { + FreezeCargo(FALSE); // frees all cargo + + if ( m_param != PARAM_PORTICO ) + { + m_main->SetMovieLock(FALSE); // you can play! + + pObj = m_main->RetSelectObject(); + m_main->SelectObject(pObj); + m_camera->SetObject(pObj); + if ( pObj == 0 ) + { + m_camera->SetType(CAMERA_BACK); + } + else + { + m_camera->SetType(pObj->RetCameraType()); + m_camera->SetDist(pObj->RetCameraDist()); + } + m_sound->Play(SOUND_BOUM, m_object->RetPosition(0)); + m_soundChannel = -1; + + m_engine->SetFogStart(m_fogStart); + } + + m_bOpen = TRUE; + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ABP_CLOSE2 ) + { + if ( m_progress < 1.0f ) + { + len = 7.0f-(1.0f-m_progress)*(7.0f+11.5f); + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, len)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, -len)); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f*(1.0f-m_progress)); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f*(1.0f-m_progress)); + } + } + else + { + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, 7.0f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, -7.0f)); + m_object->SetAngleX(10+i, 0.0f); + m_object->SetAngleX(18+i, 0.0f); + } + + m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP); + + m_phase = ABP_CLOSE; + m_progress = 0.0f; + m_speed = 1.0f/BASE_DOOR_TIME; + } + } + + if ( m_phase == ABP_CLOSE ) + { + if ( m_progress < 1.0f ) + { + angle = -(1.0f-m_progress)*124.0f*PI/180.0f; + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f+angle); + } + } + else + { + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f); + } + m_bMotor = TRUE; // lights the jet engine + + // Shock of the closing doors. + max = (int)(20.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTICRASH, time); + } + m_sound->Play(SOUND_BOUM, m_object->RetPosition(0)); + + m_soundChannel = -1; + m_bOpen = FALSE; + m_phase = ABP_TOWAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == ABP_TOWAIT ) + { + if ( m_progress < 1.0f ) + { + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 2.0f, BASE_TAKO_TIME, SOPER_STOP); + } + + vibCir.z = sinf(m_time*PI*19.01f)*(PI/400.0f); + vibCir.x = sinf(m_time*PI*19.53f)*(PI/400.0f); + vibCir.y = 0.0f; + vibCir *= m_progress*1.0f; + m_object->SetCirVibration(vibCir); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + // Particles are ejected from the reactor. + pos = m_object->RetPosition(0); + pos.y += 6.0f; + speed.x = (Rand()-0.5f)*160.0f; + speed.z = (Rand()-0.5f)*160.0f; + speed.y = -(Rand()*10.0f+10.0f); + dim.x = Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f); + } + + m_engine->SetFogStart(m_fogStart+(0.9f-m_fogStart)*m_progress); + } + else + { + m_engine->SetFogStart(0.9f); + + m_phase = ABP_TAKEOFF; + m_progress = 0.0f; + m_speed = 1.0f/BASE_TAKO_TIME; + } + } + + if ( m_phase == ABP_TAKEOFF ) + { + if ( m_progress < 1.0f ) + { + pos = m_pos; + pos.y += powf(m_progress, 2.0f)*600.0f; + m_object->SetPosition(0, pos); + MoveCargo(); // all cargo moves + + vibCir.z = sinf(m_time*PI*19.01f)*(PI/400.0f); + vibCir.x = sinf(m_time*PI*19.53f)*(PI/400.0f); + vibCir.y = 0.0f; + m_object->SetCirVibration(vibCir); + + pos = m_pos; + pos.x -= 110.0f+m_progress*250.0f; + m_terrain->MoveOnFloor(pos); + pos.y += 10.0f; + m_camera->SetScriptEye(pos); + + pos = m_object->RetPosition(0); + pos.y += 50.0f; + m_camera->SetScriptLookat(pos); + + m_engine->SetFocus(1.0f+m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + // Dust thrown to the ground. + pos = m_pos; + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + angle = Rand()*(PI*2.0f); + dist = (1.0f-m_progress)*50.0f; + p = RotatePoint(angle, dist); + speed.x = p.x; + speed.z = p.y; + speed.y = 0.0f; + dim.x = (Rand()*10.0f+10.0f)*(1.0f-m_progress); + dim.y = dim.x; + if ( dim.x >= 1.0f ) + { + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f); + } + + // Particles are ejected from the reactor. + pos = m_object->RetPosition(0); + pos.y += 6.0f; + speed.x = (Rand()-0.5f)*40.0f; + speed.z = (Rand()-0.5f)*40.0f; + time = 5.0f+150.0f*m_progress; + speed.y = -(Rand()*time+time); + time = 2.0f+m_progress*12.0f; + dim.x = Rand()*time+time; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f); + + // Black smoke from the reactor. + pos = m_object->RetPosition(0); + pos.y += 3.0f; + speed.x = (Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f); + speed.z = (Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f); + speed.y = 0.0f; + dim.x = Rand()*20.0f+20.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 10.0f, 0.0f, 2.0f); + } + } + else + { + m_soundChannel = -1; + m_event->MakeEvent(newEvent, EVENT_WIN); + m_event->AddEvent(newEvent); + + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == ABP_PORTICO_MOVE ) // advance of the gate? + { + if ( m_progress < 1.0f ) + { + pos = m_object->RetPosition(0); + pos.z -= event.rTime*5.0f; + m_object->SetPosition(0, pos); + MoveCargo(); // all cargo moves + } + else + { + m_phase = ABP_PORTICO_WAIT1; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ABP_PORTICO_WAIT1 ) // expectation the gate? + { + if ( m_progress >= 1.0f ) + { + m_phase = ABP_PORTICO_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/BASE_PORTICO_TIME_DOWN; + } + } + + if ( m_phase == ABP_PORTICO_DOWN ) // down the gate? + { + if ( m_progress < 1.0f ) + { + pos = m_object->RetPosition(0); + pos.y -= event.rTime*(10.0f/BASE_PORTICO_TIME_DOWN); + m_object->SetPosition(0, pos); + MoveCargo(); // all cargo moves + } + else + { + // Impact with the ground. + max = (int)(50.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f); + } + + m_phase = ABP_PORTICO_WAIT2; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ABP_PORTICO_WAIT2 ) // expectation the gate? + { + if ( m_progress >= 1.0f ) + { + m_phase = ABP_PORTICO_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/BASE_PORTICO_TIME_OPEN; + } + } + + if ( m_phase == ABP_PORTICO_OPEN ) // opening the gate? + { + if ( m_progress < 1.0f ) + { + } + else + { + m_phase = ABP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == ABP_TRANSIT_MOVE ) // transit in space? + { + if ( m_progress < 1.0f ) + { + pos = m_object->RetPosition(0); + pos.x += event.rTime*(2000.0f/BASE_TRANSIT_TIME); + m_object->SetPosition(0, pos); + pos.x += 60.0f; + m_camera->SetScriptLookat(pos); + } + else + { + m_object->SetAngleZ(0, 0.0f); + + m_param = PARAM_LANDING; + m_phase = ABP_START; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + EndTransit(); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP); + m_soundChannel = -1; + } + goto begin; + } + } + + if ( m_bMotor ) + { + if ( m_lastMotorParticule+m_engine->ParticuleAdapt(0.02f) <= m_time ) + { + m_lastMotorParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + + if ( event.rTime == 0.0f ) + { + vSpeed = 0.0f; + } + else + { + pos = m_object->RetPosition(0); + if ( m_phase == ABP_TRANSIT_MOVE ) + { + vSpeed = (pos.x-iPos.x)/event.rTime; + } + else + { + vSpeed = (pos.y-iPos.y)/event.rTime; + } + if ( vSpeed < 0.0f ) vSpeed *= 1.5f; + } + + pos = D3DVECTOR(0.0f, 6.0f, 0.0f); + speed.x = (Rand()-0.5f)*4.0f; + speed.z = (Rand()-0.5f)*4.0f; + speed.y = vSpeed*0.8f-(8.0f+Rand()*6.0f); + speed += pos; + pos = Transform(*mat, pos); + speed = Transform(*mat, speed); + speed -= pos; + + dim.x = 4.0f+Rand()*4.0f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTIBASE, 3.0f, 0.0f, 0.0f); + + if ( m_phase == ABP_TRANSIT_MOVE ) + { + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 12.0f; + dim.y = dim.x; + pos = D3DVECTOR(0.0f, 7.0f, 0.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f); + + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 4.0f; + dim.y = dim.x; + pos = D3DVECTOR(42.0f, 0.0f, 17.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(17.0f, 0.0f, 42.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(42.0f, 0.0f, -17.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(17.0f, 0.0f, -42.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(-42.0f, 0.0f, 17.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(-17.0f, 0.0f, 42.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(-42.0f, 0.0f, -17.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + pos = D3DVECTOR(-17.0f, 0.0f, -42.0f); + pos.x += (Rand()-0.5f)*2.0f; pos.z += (Rand()-0.5f)*2.0f; + pos = Transform(*mat, pos); + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f); + + pos = D3DVECTOR(42.0f, -2.0f, 17.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[0], pos); + pos = D3DVECTOR(17.0f, -2.0f, 42.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[1], pos); + pos = D3DVECTOR(42.0f, -2.0f, -17.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[2], pos); + pos = D3DVECTOR(17.0f, -2.0f, -42.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[3], pos); + pos = D3DVECTOR(-42.0f, -2.0f, 17.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[4], pos); + pos = D3DVECTOR(-17.0f, -2.0f, 42.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[5], pos); + pos = D3DVECTOR(-42.0f, -2.0f, -17.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[6], pos); + pos = D3DVECTOR(-17.0f, -2.0f, -42.0f); + pos = Transform(*mat, pos); + m_particule->SetPosition(m_partiChannel[7], pos); + } + } + } + + if ( m_soundChannel != -1 ) + { + pos = m_engine->RetEyePt(); + m_sound->Position(m_soundChannel, pos); + } + + return TRUE; +} + +// Stops the controller. + +BOOL CAutoBase::Abort() +{ + Event newEvent; + CObject* pObj; + int i; + + if ( m_phase == ABP_TRANSIT_MOVE ) // transit ? + { + m_object->SetAngleZ(0, 0.0f); + + m_param = PARAM_LANDING; + m_phase = ABP_START; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + EndTransit(); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP); + m_soundChannel = -1; + } + return TRUE; + } + + if ( m_param == PARAM_PORTICO ) // gate on the porch? + { + m_object->SetPosition(0, m_finalPos); + MoveCargo(); // all cargo moves + + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f); + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f)); + } + } + else + { + if ( m_phase == ABP_LAND || + m_phase == ABP_OPENWAIT || + m_phase == ABP_OPEN || + m_phase == ABP_OPEN2 ) // Landing? + { + m_bMotor = FALSE; // put out the jet engine + m_bOpen = TRUE; + + m_object->SetPosition(0, m_pos); // setting down + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + MoveCargo(); // all cargo moves + for ( i=0 ; i<8 ; i++ ) + { + m_object->SetAngleZ(1+i, PI/2.0f-124.0f*PI/180.0f); + m_object->SetAngleX(10+i, -10.0f*PI/180.0f); + m_object->SetAngleX(18+i, 10.0f*PI/180.0f); + m_object->SetPosition(10+i, D3DVECTOR(23.5f, 0.0f, -11.5f)); + m_object->SetPosition(18+i, D3DVECTOR(23.5f, 0.0f, 11.5f)); + } + + m_main->SetMovieLock(FALSE); // you can play! + + pObj = m_main->RetSelectObject(); + m_main->SelectObject(pObj); + m_camera->SetObject(pObj); + if ( pObj == 0 ) + { + m_camera->SetType(CAMERA_BACK); + } + else + { + m_camera->SetType(pObj->RetCameraType()); + m_camera->SetDist(pObj->RetCameraDist()); + } + + m_engine->SetFogStart(m_fogStart); + } + + if ( m_phase == ABP_CLOSE2 || + m_phase == ABP_CLOSE || + m_phase == ABP_TOWAIT || + m_phase == ABP_TAKEOFF ) // off? + { + m_event->MakeEvent(newEvent, EVENT_WIN); + m_event->AddEvent(newEvent); + } + } + + m_object->SetAngleZ(0, 0.0f); + FreezeCargo(FALSE); // frees all cargo + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_phase = ABP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoBase::RetError() +{ + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoBase::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + float sleep, delay, magnetic, progress; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + ddim.x = dim.x*1.5f; + ddim.y = dim.y*1.5f; + +//? pos.x = ox+sx*7.25f; +//? pos.y = oy+sy*0.25f; +//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP); + + pos.x = ox+sx*8.00f; + pos.y = oy+sy*0.25f; + pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF); + + if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) ) + { + pos.x = ox+sx*10.2f; + pos.y = oy+sy*0.5f; + ddim.x = dim.x*1.0f; + ddim.y = dim.y*1.0f; + pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT); + } + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 100, EVENT_OBJECT_TYPE); + + UpdateInterface(); + + return TRUE; +} + +// Updates the status of all interface buttons. + +void CAutoBase::UpdateInterface() +{ + CWindow* pw; + + if ( !m_object->RetSelect() ) return; + + CAuto::UpdateInterface(); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); +} + + +// Freeze or frees all cargo. + +void CAutoBase::FreezeCargo(BOOL bFreeze) +{ + CObject* pObj; + CPhysics* physics; + D3DVECTOR oPos; + float dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + pObj->SetCargo(FALSE); + + if ( pObj == m_object ) continue; // yourself? + if ( pObj->RetTruck() != 0 ) continue; // transport object? + + oPos = pObj->RetPosition(0); + dist = Length2d(m_pos, oPos); + if ( dist < 32.0f ) + { + if ( bFreeze ) + { + pObj->SetCargo(TRUE); + } + + physics = pObj->RetPhysics(); + if ( physics != 0 ) + { + physics->SetFreeze(bFreeze); + } + } + } +} + +// All cargo moves vertically with the ship. + +void CAutoBase::MoveCargo() +{ + CObject* pObj; + D3DVECTOR oPos, sPos; + int i; + + sPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetCargo() ) continue; + + oPos = pObj->RetPosition(0); + oPos.y = sPos.y+30.0f; + oPos.y += pObj->RetCharacter()->height; + oPos.x += sPos.x-m_lastPos.x; + oPos.z += sPos.z-m_lastPos.z; + pObj->SetPosition(0, oPos); + } + + m_lastPos = sPos; +} + + +// Checks whether it is possible to close the doors. + +Error CAutoBase::CheckCloseDoor() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float oRad, dist; + int i, j; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; // yourself? + if ( !pObj->RetActif() ) continue; // inactive? + + type = pObj->RetType(); + if ( type == OBJECT_PORTICO ) continue; + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRad) ) + { + dist = Length2d(m_pos, oPos); + if ( dist+oRad > 32.0f && + dist-oRad < 72.0f ) + { + return ERR_BASE_DLOCK; + } + + if ( type == OBJECT_HUMAN && + dist+oRad > 32.0f ) + { + return ERR_BASE_DHUMAN; + } + } + } + return ERR_OK; +} + + +// Start a transit. + +void CAutoBase::BeginTransit() +{ + BOOL bFull, bQuarter; + + if ( m_param == PARAM_TRANSIT2 ) + { + strcpy(m_bgBack, "back01.tga"); // clouds orange / blue + } + else if ( m_param == PARAM_TRANSIT3 ) + { + strcpy(m_bgBack, "back22.tga"); // blueberries clouds + } + else + { +#if _DEMO + strcpy(m_bgBack, "back46b.tga"); // paintings +#else + strcpy(m_bgBack, "back46.tga"); // paintings +#endif + } + + m_engine->SetFogStart(0.9f); // hardly any fog + m_engine->SetDeepView(2000.0f); // we see very far + m_engine->ApplyChange(); + + m_engine->RetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, bFull, bQuarter); + m_engine->FreeTexture(m_bgName); + + m_engine->SetBackground(m_bgBack, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + m_engine->LoadTexture(m_bgBack); + + m_cloud->SetEnable(FALSE); // cache clouds + m_planet->SetMode(1); +} + +// End of a transit. + +void CAutoBase::EndTransit() +{ + m_engine->SetFogStart(m_fogStart); // gives initial fog + m_engine->SetDeepView(m_deepView); // gives initial depth + m_engine->ApplyChange(); + + m_engine->FreeTexture(m_bgBack); + + m_engine->SetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown); + m_engine->LoadTexture(m_bgName); + + m_cloud->SetEnable(TRUE); // gives the clouds + m_planet->SetMode(0); + + m_main->StartMusic(); +} + diff --git a/src/object/auto/autobase.h b/src/object/auto/autobase.h new file mode 100644 index 0000000..7e0093a --- /dev/null +++ b/src/object/auto/autobase.h @@ -0,0 +1,122 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autobase.h + +#ifndef _AUTOBASE_H_ +#define _AUTOBASE_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +#define PARAM_STOP 0 // run=0 -> stops and open +#define PARAM_LANDING 1 // run=1 -> landing +#define PARAM_PORTICO 2 // run=2 -> gate on the ground +#define PARAM_FIXSCENE 3 // run=3 -> open and stops to win / lost +#define PARAM_TRANSIT1 11 // run=11 -> transit in space +#define PARAM_TRANSIT2 12 // run=12 -> transit in space +#define PARAM_TRANSIT3 13 // run=13 -> transit in space + + +enum AutoBasePhase +{ + ABP_WAIT = 1, // expected + ABP_START = 2, // start-up + + ABP_LAND = 3, // landing + ABP_OPENWAIT = 4, // wait before opening + ABP_OPEN = 5, // opens the gate + ABP_OPEN2 = 6, // opens supplements + ABP_LDWAIT = 7, // expected + + ABP_CLOSE2 = 8, // closes supplements + ABP_CLOSE = 9, // closes gate + ABP_TOWAIT = 10, // wait before takeoff + ABP_TAKEOFF = 11, // take-off + + ABP_PORTICO_MOVE = 12, // gate advance + ABP_PORTICO_WAIT1= 13, // gate expected + ABP_PORTICO_DOWN = 14, // gate down + ABP_PORTICO_WAIT2= 15, // gate expected + ABP_PORTICO_OPEN = 16, // gate opens + + ABP_TRANSIT_MOVE = 17, // transit - moving +}; + + + +class CAutoBase : public CAuto +{ +public: + CAutoBase(CInstanceManager* iMan, CObject* object); + ~CAutoBase(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + BOOL Abort(); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + +protected: + void UpdateInterface(); + void FreezeCargo(BOOL bFreeze); + void MoveCargo(); + Error CheckCloseDoor(); + void BeginTransit(); + void EndTransit(); + +protected: + AutoBasePhase m_phase; + BOOL m_bOpen; + float m_progress; + float m_speed; + float m_lastParticule; + float m_lastMotorParticule; + float m_fogStart; + float m_deepView; + D3DVECTOR m_pos; + D3DVECTOR m_posSound; + D3DVECTOR m_finalPos; + D3DVECTOR m_lastPos; + int m_param; + int m_soundChannel; + int m_partiChannel[8]; + + char m_bgBack[100]; + char m_bgName[100]; + D3DCOLOR m_bgUp; + D3DCOLOR m_bgDown; + D3DCOLOR m_bgCloudUp; + D3DCOLOR m_bgCloudDown; +}; + + +#endif //_AUTOBASE_H_ diff --git a/src/object/auto/autoconvert.cpp b/src/object/auto/autoconvert.cpp new file mode 100644 index 0000000..ae213e3 --- /dev/null +++ b/src/object/auto/autoconvert.cpp @@ -0,0 +1,546 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoconvert.h" + + + + +// Object's constructor. + +CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = ACP_STOP; + m_bResetDelete = FALSE; + m_soundChannel = -1; +} + +// Object's destructor. + +CAutoConvert::~CAutoConvert() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoConvert::DeleteObject(BOOL bAll) +{ + CObject* fret; + + if ( !bAll ) + { + fret = SearchStone(OBJECT_STONE); + if ( fret != 0 ) + { + fret->DeleteObject(); // destroy the stone + delete fret; + } + } + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoConvert::Init() +{ + m_phase = ACP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoConvert::EventProcess(const Event &event) +{ + CObject* fret; + D3DVECTOR pos, speed; + FPOINT dim, c, p; + float angle; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + angle = (Rand()-0.5f)*0.3f; + m_object->SetAngleY(1, angle); + m_object->SetAngleY(2, angle); + m_object->SetAngleY(3, angle+PI); + + m_object->SetAngleX(2, -PI*0.35f*(0.8f+Rand()*0.2f)); + m_object->SetAngleX(3, -PI*0.35f*(0.8f+Rand()*0.2f)); + } + return TRUE; + } + + EventProgress(event.rTime); + + if ( m_phase == ACP_STOP ) return TRUE; + + if ( m_phase == ACP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + fret = SearchStone(OBJECT_STONE); // Has stone transformed? + if ( fret == 0 || SearchVehicle() ) + { + m_phase = ACP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + else + { + fret->SetLock(TRUE); // stone usable + + SetBusy(TRUE); + InitProgressTotal(3.0f+10.0f+1.5f); + UpdateInterface(); + + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.0f); + m_bSoundClose = FALSE; + + m_phase = ACP_CLOSE; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + } + + if ( m_phase == ACP_CLOSE ) + { + if ( m_progress < 1.0f ) + { + if ( m_progress >= 0.8f && !m_bSoundClose ) + { + m_bSoundClose = TRUE; + m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 0.8f); + } + angle = -PI*0.35f*(1.0f-Bounce(m_progress, 0.85f, 0.05f)); + m_object->SetAngleX(2, angle); + m_object->SetAngleX(3, angle); + } + else + { + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(3, 0.0f); + + m_soundChannel = m_sound->Play(SOUND_CONVERT, m_object->RetPosition(0), 0.0f, 0.25f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.00f, 4.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 4.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 0.5f, SOPER_STOP); + + m_phase = ACP_ROTATE; + m_progress = 0.0f; + m_speed = 1.0f/10.0f; + } + } + + if ( m_phase == ACP_ROTATE ) + { + if ( m_progress < 1.0f ) + { + if ( m_progress < 0.5f ) + { + angle = powf((m_progress*2.0f)*5.0f, 2.0f); // accelerates + } + else + { + angle = -powf((2.0f-m_progress*2.0f)*5.0f, 2.0f); // slows + } + m_object->SetAngleY(1, angle); + m_object->SetAngleY(2, angle); + m_object->SetAngleY(3, angle+PI); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + c.x = pos.x; + c.y = pos.z; + p.x = c.x; + p.y = c.y+6.0f; + p = RotatePoint(c, Rand()*PI*2.0f, p); + pos.x = p.x; + pos.z = p.y; + pos.y += 1.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = Rand()*2.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f); + } + } + else + { + m_object->SetAngleY(1, 0.0f); + m_object->SetAngleY(2, 0.0f); + m_object->SetAngleY(3, PI); + + fret = SearchStone(OBJECT_STONE); + if ( fret != 0 ) + { + m_bResetDelete = ( fret->RetResetCap() != RESET_NONE ); + fret->DeleteObject(); // destroy the stone + delete fret; + } + + CreateMetal(); // Create the metal + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.5f); + + m_phase = ACP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ACP_OPEN ) + { + if ( m_progress < 1.0f ) + { + angle = -PI*0.35f*Bounce(m_progress, 0.7f, 0.2f); + m_object->SetAngleX(2, angle); + m_object->SetAngleX(3, angle); + + if ( m_progress < 0.9f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*6.0f; + pos.z += (Rand()-0.5f)*6.0f; + pos.y += Rand()*4.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = Rand()*4.0f+3.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); + } + } + else + { + m_soundChannel = -1; + m_object->SetAngleX(2, -PI*0.35f); + m_object->SetAngleX(3, -PI*0.35f); + + SetBusy(FALSE); + UpdateInterface(); + + m_phase = ACP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + return TRUE; +} + +// Returns an error due the state of the automation. + +Error CAutoConvert::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + if ( m_phase == ACP_WAIT ) return ERR_CONVERT_EMPTY; + return ERR_OK; +} + +// Cancels the current transformation. + +BOOL CAutoConvert::Abort() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_object->SetAngleY(1, 0.0f); + m_object->SetAngleY(2, 0.0f); + m_object->SetAngleY(3, PI); + m_object->SetAngleX(2, -PI*0.35f); + m_object->SetAngleX(3, -PI*0.35f); + + m_phase = ACP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + SetBusy(FALSE); + UpdateInterface(); + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoConvert::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 103, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Saves all parameters of the controller. + +BOOL CAutoConvert::Write(char *line) +{ + char name[100]; + + if ( m_phase == ACP_STOP || + m_phase == ACP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoConvert::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoConvertPhase)OpInt(line, "aPhase", ACP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + +// Searches for the object before or during processing. + +CObject* CAutoConvert::SearchStone(ObjectType type) +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType oType; + float dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( oType != type ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, cPos); + + if ( dist <= 5.0f ) return pObj; + } + + return 0; +} + +// Search if a vehicle is too close. + +BOOL CAutoConvert::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType type; + float oRadius, dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_METAL && + type != OBJECT_URANIUM && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BULLET && + type != OBJECT_BBOX && + type != OBJECT_TNT && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, cPos)-oRadius; + + if ( dist < 8.0f ) return TRUE; + } + + return FALSE; +} + +// Creates an object metal. + +void CAutoConvert::CreateMetal() +{ + D3DVECTOR pos; + float angle; + CObject* fret; + + pos = m_object->RetPosition(0); + angle = m_object->RetAngleY(0); + + fret = new CObject(m_iMan); + if ( !fret->CreateResource(pos, angle, OBJECT_METAL) ) + { + delete fret; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return; + } + + if ( m_bResetDelete ) + { + fret->SetResetCap(RESET_DELETE); + } + + m_displayText->DisplayError(INFO_CONVERT, m_object); +} + diff --git a/src/object/auto/autoconvert.h b/src/object/auto/autoconvert.h new file mode 100644 index 0000000..2e35e24 --- /dev/null +++ b/src/object/auto/autoconvert.h @@ -0,0 +1,82 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoconvert.h + +#ifndef _AUTOCONVERT_H_ +#define _AUTOCONVERT_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoConvertPhase +{ + ACP_STOP = 1, + ACP_WAIT = 2, + ACP_CLOSE = 3, // close the cover + ACP_ROTATE = 4, // turn the cover + ACP_OPEN = 5, // opens the cover +}; + + + +class CAutoConvert : public CAuto +{ +public: + CAutoConvert(CInstanceManager* iMan, CObject* object); + ~CAutoConvert(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + BOOL Abort(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchStone(ObjectType type); + BOOL SearchVehicle(); + void CreateMetal(); + +protected: + AutoConvertPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + BOOL m_bResetDelete; + BOOL m_bSoundClose; + int m_soundChannel; +}; + + +#endif //_AUTOCONVERT_H_ diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp new file mode 100644 index 0000000..d2541c5 --- /dev/null +++ b/src/object/auto/autoderrick.cpp @@ -0,0 +1,605 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoderrick.h" + + + +#define DERRICK_DELAY 10.0f // duration of the extraction +#define DERRICK_DELAYu 30.0f // same, but for uranium + + + + +// Object's constructor. + +CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = ADP_WAIT; // paused until the first Init () + m_soundChannel = -1; +} + +// Object's destructor. + +CAutoDerrick::~CAutoDerrick() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoDerrick::DeleteObject(BOOL bAll) +{ + CObject* fret; + + if ( !bAll ) + { + fret = SearchFret(); + if ( fret != 0 && fret->RetLock() ) + { + fret->DeleteObject(); + delete fret; + } + } + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoDerrick::Init() +{ + D3DMATRIX* mat; + D3DVECTOR pos; + TerrainRes res; + + pos = m_object->RetPosition(0); + res = m_terrain->RetResource(pos); + + if ( res == TR_STONE || + res == TR_URANIUM || + res == TR_KEYa || + res == TR_KEYb || + res == TR_KEYc || + res == TR_KEYd ) + { + m_type = OBJECT_FRET; + if ( res == TR_STONE ) m_type = OBJECT_STONE; + if ( res == TR_URANIUM ) m_type = OBJECT_URANIUM; + if ( res == TR_KEYa ) m_type = OBJECT_KEYa; + if ( res == TR_KEYb ) m_type = OBJECT_KEYb; + if ( res == TR_KEYc ) m_type = OBJECT_KEYc; + if ( res == TR_KEYd ) m_type = OBJECT_KEYd; + + m_phase = ADP_EXCAVATE; + m_progress = 0.0f; + m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY); + } + else + { + m_phase = ADP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f; + } + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + m_lastTrack = 0.0f; + + pos = D3DVECTOR(7.0f, 0.0f, 0.0f); + mat = m_object->RetWorldMatrix(0); + pos = Transform(*mat, pos); + m_terrain->MoveOnFloor(pos); + m_fretPos = pos; +} + + +// Management of an event. + +BOOL CAutoDerrick::EventProcess(const Event &event) +{ + CObject* fret; + D3DVECTOR pos, speed; + FPOINT dim; + float angle, duration, factor; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_phase == ADP_WAIT ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + pos.x = 0.0f; + pos.z = 0.0f; + pos.y = -2.0f*Rand(); + m_object->SetPosition(1, pos); // up / down the drill + + m_object->SetAngleY(1, Rand()*0.5f); // rotates the drill + } + return TRUE; + } + + if ( m_phase == ADP_EXCAVATE ) + { + if ( m_soundChannel == -1 ) + { + if ( m_type == OBJECT_URANIUM ) + { + factor = DERRICK_DELAYu/DERRICK_DELAY; + } + else + { + factor = 1.0f; + } + m_soundChannel = m_sound->Play(SOUND_DERRICK, m_object->RetPosition(0), 1.0f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f*factor, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.3f, 6.0f*factor, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f, SOPER_STOP); + } + + if ( m_progress >= 6.0f/16.0f && // penetrates into the ground? + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress >= 6.0f/16.0f && // penetrates into the ground? + m_lastTrack+m_engine->ParticuleAdapt(0.5f) <= m_time ) + { + m_lastTrack = m_time; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*12.0f; + speed.z = (Rand()-0.5f)*12.0f; + speed.y = Rand()*10.0f+10.0f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Rand()*2.0f+2.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK5, + duration, Rand()*10.0f+15.0f, + duration*0.2f, 1.0f); + } + + if ( m_progress < 1.0f ) + { + pos.x = 0.0f; + pos.z = 0.0f; + pos.y = -m_progress*16.0f; + m_object->SetPosition(1, pos); // down the drill + + angle = m_object->RetAngleY(1); + angle += event.rTime*8.0f; + m_object->SetAngleY(1, angle); // rotates the drill + } + else + { + m_phase = ADP_ASCEND; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + + if ( m_phase == ADP_ASCEND ) + { + if ( m_progress <= 7.0f/16.0f && + m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress <= 4.0f/16.0f && + m_lastTrack+m_engine->ParticuleAdapt(1.0f) <= m_time ) + { + m_lastTrack = m_time; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*12.0f; + speed.z = (Rand()-0.5f)*12.0f; + speed.y = Rand()*10.0f+10.0f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Rand()*2.0f+2.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK5, + duration, Rand()*10.0f+15.0f, + duration*0.2f, 1.0f); + } + + if ( m_progress < 1.0f ) + { + pos.x = 0.0f; + pos.z = 0.0f; + pos.y = -(1.0f-m_progress)*16.0f; + m_object->SetPosition(1, pos); // back the drill + + angle = m_object->RetAngleY(1); + angle -= event.rTime*2.0f; + m_object->SetAngleY(1, angle); // rotates the drill + } + else + { + m_soundChannel = -1; + m_bSoundFall = FALSE; + + m_phase = ADP_EXPORT; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + + if ( m_phase == ADP_ISFREE ) + { + if ( m_progress >= 1.0f ) + { + m_bSoundFall = FALSE; + + m_phase = ADP_EXPORT; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + + if ( m_phase == ADP_EXPORT ) + { + if ( m_progress == 0.0f ) + { + if ( SearchFree(m_fretPos) ) + { + angle = m_object->RetAngleY(0); + CreateFret(m_fretPos, angle, m_type, 16.0f); + } + else + { + m_phase = ADP_ISFREE; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + return TRUE; + } + } + + fret = SearchFret(); + + if ( fret != 0 && + m_progress <= 0.5f && + m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time ) + { + m_lastParticule = m_time; + + if ( m_progress < 0.3f ) + { + pos = fret->RetPosition(0); + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + pos.y += (Rand()-0.5f)*5.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 3.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIRE, 1.0f, 0.0f, 0.0f); + } + else + { + pos = fret->RetPosition(0); + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + pos.y += Rand()*2.5f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f); + } + } + + if ( m_progress < 1.0f ) + { + if ( fret != 0 ) + { + pos = fret->RetPosition(0); + pos.y -= event.rTime*20.0f; // grave + if ( !m_bSoundFall && pos.y < m_fretPos.y ) + { + m_sound->Play(SOUND_BOUM, m_fretPos); + m_bSoundFall = TRUE; + } + if ( pos.y < m_fretPos.y ) + { + pos.y = m_fretPos.y; + fret->SetLock(FALSE); // object usable + } + fret->SetPosition(0, pos); + } + } + else + { + if ( ExistKey() ) // key already exists? + { + m_phase = ADP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/10.0f; + } + else + { + m_phase = ADP_EXCAVATE; + m_progress = 0.0f; + m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY); + } + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoDerrick::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 109, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Saves all parameters of the controller. + +BOOL CAutoDerrick::Write(char *line) +{ + char name[100]; + + if ( m_phase == ADP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoDerrick::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoDerrickPhase)OpInt(line, "aPhase", ADP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + +// Seeks the subject cargo. + +CObject* CAutoDerrick::SearchFret() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_DERRICK ) continue; + + oPos = pObj->RetPosition(0); + + if ( oPos.x == m_fretPos.x && + oPos.z == m_fretPos.z ) return pObj; + } + + return 0; +} + +// Seeks if a site is free. + +BOOL CAutoDerrick::SearchFree(D3DVECTOR pos) +{ + CObject* pObj; + D3DVECTOR sPos; + ObjectType type; + float sRadius, distance; + int i, j; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_DERRICK ) continue; + + j = 0; + while ( pObj->GetCrashSphere(j++, sPos, sRadius) ) + { + distance = Length(sPos, pos); + distance -= sRadius; + if ( distance < 2.0f ) return FALSE; // location occupied + } + } + + return TRUE; // location free +} + +// Create a transportable object. + +void CAutoDerrick::CreateFret(D3DVECTOR pos, float angle, ObjectType type, + float height) +{ + CObject* fret; + + fret = new CObject(m_iMan); + if ( !fret->CreateResource(pos, angle, type) ) + { + delete fret; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return; + } + fret->SetLock(TRUE); // object not yet usable + + if ( m_object->RetResetCap() == RESET_MOVE ) + { + fret->SetResetCap(RESET_DELETE); + } + + pos = fret->RetPosition(0); + pos.y += height; + fret->SetPosition(0, pos); +} + +// Look if there is already a key. + +BOOL CAutoDerrick::ExistKey() +{ + CObject* pObj; + ObjectType type; + int i; + + if ( m_type != OBJECT_KEYa && + m_type != OBJECT_KEYb && + m_type != OBJECT_KEYc && + m_type != OBJECT_KEYd ) return FALSE; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == m_type ) return TRUE; + } + + return FALSE; +} + + +// Returns an error due the state of the automaton. + +Error CAutoDerrick::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + if ( m_phase == ADP_WAIT ) return ERR_DERRICK_NULL; + return ERR_OK; +} + + diff --git a/src/object/auto/autoderrick.h b/src/object/auto/autoderrick.h new file mode 100644 index 0000000..6c9293d --- /dev/null +++ b/src/object/auto/autoderrick.h @@ -0,0 +1,84 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoderrick.h + +#ifndef _AUTODERRICK_H_ +#define _AUTODERRICK_H_ + + +#include "object.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + + +enum AutoDerrickPhase +{ + ADP_WAIT = 1, + ADP_EXCAVATE = 2, // down the drill + ADP_ASCEND = 3, // up the drill + ADP_EXPORT = 4, // exports matter + ADP_ISFREE = 5, // expected material loss +}; + + + +class CAutoDerrick : public CAuto +{ +public: + CAutoDerrick(CInstanceManager* iMan, CObject* object); + ~CAutoDerrick(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchFret(); + BOOL SearchFree(D3DVECTOR pos); + void CreateFret(D3DVECTOR pos, float angle, ObjectType type, float height); + BOOL ExistKey(); + +protected: + AutoDerrickPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + float m_lastTrack; + D3DVECTOR m_fretPos; + int m_soundChannel; + BOOL m_bSoundFall; +}; + + +#endif //_AUTODERRICK_H_ diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp new file mode 100644 index 0000000..11dc0ba --- /dev/null +++ b/src/object/auto/autodestroyer.cpp @@ -0,0 +1,397 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "pyro.h" +#include "sound.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "robotmain.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autodestroyer.h" + + + + +// Object's constructor. + +CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = ADEP_WAIT; // paused until the first Init () +} + +// Destructive of the object. + +CAutoDestroyer::~CAutoDestroyer() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoDestroyer::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoDestroyer::Init() +{ + m_phase = ADEP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/0.5f; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoDestroyer::EventProcess(const Event &event) +{ + CObject* scrap; + CPyro* pyro; + D3DVECTOR pos, speed; + FPOINT dim; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + if ( m_phase == ADEP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + scrap = SearchPlastic(); + if ( scrap == 0 ) + { + m_phase = ADEP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/0.5f; + } + else + { + scrap->SetLock(TRUE); // usable waste +//? scrap->SetTruck(m_object); // usable waste + + if ( SearchVehicle() ) + { + m_phase = ADEP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/0.5f; + } + else + { + m_sound->Play(SOUND_PSHHH2, m_object->RetPosition(0), 1.0f, 1.0f); + + m_phase = ADEP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_bExplo = FALSE; + } + } + } + } + + if ( m_phase == ADEP_DOWN ) + { + if ( m_progress >= 0.3f-0.05f && !m_bExplo ) + { + scrap = SearchPlastic(); + if ( scrap != 0 ) + { + pyro = new CPyro(m_iMan); + pyro->Create(PT_FRAGT, scrap); + } + m_bExplo = TRUE; + } + + if ( m_progress < 1.0f ) + { + pos = D3DVECTOR(0.0f, -10.0f, 0.0f); + pos.y = -Bounce(m_progress, 0.3f)*10.0f; + m_object->SetPosition(1, pos); + } + else + { + m_object->SetPosition(1, D3DVECTOR(0.0f, -10.0f, 0.0f)); + m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0)); + + m_phase = ADEP_REPAIR; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ADEP_REPAIR ) + { + if ( m_progress < 1.0f ) + { + } + else + { + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f); + + m_phase = ADEP_UP; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + + if ( m_phase == ADEP_UP ) + { + if ( m_progress < 1.0f ) + { + pos = D3DVECTOR(0.0f, -10.0f, 0.0f); + pos.y = -(1.0f-m_progress)*10.0f; + m_object->SetPosition(1, pos); + } + else + { + m_object->SetPosition(1, D3DVECTOR(0.0f, 0.0f, 0.0f)); + + m_phase = ADEP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/0.5f; + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoDestroyer::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Seeks plate waste in the destroyer. + +CObject* CAutoDestroyer::SearchPlastic() +{ + CObject* pObj; + D3DVECTOR sPos, oPos; + ObjectType type; + float dist; + int i; + + sPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_SCRAP4 && + type != OBJECT_SCRAP5 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, sPos); + if ( dist <= 5.0f ) return pObj; + } + + return 0; +} + +// Seeks if one vehicle is too close. + +BOOL CAutoDestroyer::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType type; + float oRadius, dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, cPos)-oRadius; + + if ( dist < 20.0f ) return TRUE; + } + + return FALSE; +} + + +// Returns an error due the state of the automation. + +Error CAutoDestroyer::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoDestroyer::Write(char *line) +{ + char name[100]; + + if ( m_phase == ADEP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoDestroyer::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoDestroyerPhase)OpInt(line, "aPhase", ADEP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autodestroyer.h b/src/object/auto/autodestroyer.h new file mode 100644 index 0000000..a69f832 --- /dev/null +++ b/src/object/auto/autodestroyer.h @@ -0,0 +1,76 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autodestroyer.h + +#ifndef _AUTODESTROYER_H_ +#define _AUTODESTROYER_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoDestroyerPhase +{ + ADEP_WAIT = 1, // expected metal + ADEP_DOWN = 2, // down the cover + ADEP_REPAIR = 3, // built the vehicle + ADEP_UP = 4, // up the cover +}; + + + +class CAutoDestroyer : public CAuto +{ +public: + CAutoDestroyer(CInstanceManager* iMan, CObject* object); + ~CAutoDestroyer(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchPlastic(); + BOOL SearchVehicle(); + +protected: + AutoDestroyerPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + BOOL m_bExplo; +}; + + +#endif //_AUTODESTROYER_H_ diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp new file mode 100644 index 0000000..6e57fcc --- /dev/null +++ b/src/object/auto/autoegg.cpp @@ -0,0 +1,375 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "pyro.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoegg.h" + + + +// Object's constructor. + +CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_type = OBJECT_NULL; + m_value = 0.0f; + m_string[0] = 0; + + m_param = 0; + m_phase = AEP_NULL; + Init(); +} + +// Object's destructor. + +CAutoEgg::~CAutoEgg() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoEgg::DeleteObject(BOOL bAll) +{ + CObject* alien; + + CAuto::DeleteObject(bAll); + + if ( !bAll ) + { + alien = SearchAlien(); + if ( alien != 0 ) + { + // Probably the intended action + // Original code: ( alien->RetZoom(0) == 1.0f ) + if ( alien->RetZoomY(0) == 1.0f ) + { + alien->SetLock(FALSE); + alien->SetActivity(TRUE); // the insect is active + } + else + { + alien->DeleteObject(); + delete alien; + } + } + } +} + + +// Initialize the object. + +void CAutoEgg::Init() +{ + CObject* alien; + + alien = SearchAlien(); + if ( alien == 0 ) + { + m_phase = AEP_NULL; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + m_time = 0.0f; + return; + } + + m_phase = AEP_INCUB; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + m_time = 0.0f; + + m_type = alien->RetType(); + + if ( m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE ) + { + alien->SetZoom(0, 0.2f); + } + if ( m_type == OBJECT_WORM ) + { + alien->SetZoom(0, 0.01f); // invisible ! + } + alien->SetLock(TRUE); + alien->SetActivity(FALSE); +} + + +// Gives a value. + +BOOL CAutoEgg::SetType(ObjectType type) +{ + m_type = type; + return TRUE; +} + +// Gives a value. + +BOOL CAutoEgg::SetValue(int rank, float value) +{ + if ( rank != 0 ) return FALSE; + m_value = value; + return TRUE; +} + +// Gives the string. + +BOOL CAutoEgg::SetString(char *string) +{ + strcpy(m_string, string); + return TRUE; +} + + +// Start object. + +void CAutoEgg::Start(int param) +{ + if ( m_type == OBJECT_NULL ) return; + if ( m_value == 0.0f ) return; + + m_phase = AEP_DELAY; + m_progress = 0.0f; + m_speed = 1.0f/m_value; + + m_param = param; +} + + +// Management of an event. + +BOOL CAutoEgg::EventProcess(const Event &event) +{ + CObject* alien; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_phase == AEP_NULL ) return TRUE; + + if ( m_phase == AEP_DELAY ) + { + m_progress += event.rTime*m_speed; + if ( m_progress < 1.0f ) return TRUE; + + alien = new CObject(m_iMan); + if ( !alien->CreateInsect(m_object->RetPosition(0), m_object->RetAngleY(0), m_type) ) + { + delete alien; + m_phase = AEP_DELAY; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + return TRUE; + } + alien->SetActivity(FALSE); + alien->ReadProgram(0, m_string); + alien->RunProgram(0); + Init(); + } + + alien = SearchAlien(); + if ( alien == 0 ) return TRUE; + alien->SetActivity(FALSE); + + m_progress += event.rTime*m_speed; + + if ( m_phase == AEP_ZOOM ) + { + if ( m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE ) + { + alien->SetZoom(0, 0.2f+m_progress*0.8f); // Others push + } + } + + return TRUE; +} + +// Indicates whether the controller has completed its activity. + +Error CAutoEgg::IsEnded() +{ + CObject* alien; + CPyro* pyro; + + if ( m_phase == AEP_DELAY ) + { + return ERR_CONTINUE; + } + + alien = SearchAlien(); + if ( alien == 0 ) return ERR_STOP; + + if ( m_phase == AEP_INCUB ) + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = AEP_ZOOM; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + + if ( m_phase == AEP_ZOOM ) + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_EGG, m_object); // exploding egg + + alien->SetZoom(0, 1.0f); // this is a big boy now + + m_phase = AEP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + + if ( m_phase == AEP_WAIT ) + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + alien->SetLock(FALSE); + alien->SetActivity(TRUE); // the insect is active + } + + return ERR_STOP; +} + + +// Returns an error due the state of the automation. + +Error CAutoEgg::RetError() +{ + return ERR_OK; +} + + +// Seeking the insect that starts in the egg. + +CObject* CAutoEgg::SearchAlien() +{ + CObject* pObj; + CObject* pBest; + D3DVECTOR cPos, oPos; + ObjectType type; + float dist, min; + int i; + + cPos = m_object->RetPosition(0); + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetTruck() != 0 ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_ANT && + type != OBJECT_BEE && + type != OBJECT_SPIDER && + type != OBJECT_WORM ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist < 8.0f && dist < min ) + { + min = dist; + pBest = pObj; + } + } + return pBest; +} + + +// Saves all parameters of the controller. + +BOOL CAutoEgg::Write(char *line) +{ + char name[100]; + + if ( m_phase == AEP_NULL ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.5f", m_speed); + strcat(line, name); + + sprintf(name, " aParamType=%s", GetTypeObject(m_type)); + strcat(line, name); + + sprintf(name, " aParamValue1=%.2f", m_value); + strcat(line, name); + + sprintf(name, " aParamString=\"%s\"", m_string); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoEgg::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoEggPhase)OpInt(line, "aPhase", AEP_NULL); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + m_type = OpTypeObject(line, "aParamType", OBJECT_NULL); + m_value = OpFloat(line, "aParamValue1", 0.0f); + OpString(line, "aParamString", m_string); + + return TRUE; +} + diff --git a/src/object/auto/autoegg.h b/src/object/auto/autoegg.h new file mode 100644 index 0000000..4340a9b --- /dev/null +++ b/src/object/auto/autoegg.h @@ -0,0 +1,83 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoegg.h + +#ifndef _AUTOEGG_H_ +#define _AUTOEGG_H_ + + +#include "object.h" +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoEggPhase +{ + AEP_NULL = 0, + AEP_DELAY = 1, + AEP_INCUB = 3, + AEP_ZOOM = 4, + AEP_WAIT = 5, +}; + + + +class CAutoEgg : public CAuto +{ +public: + CAutoEgg(CInstanceManager* iMan, CObject* object); + ~CAutoEgg(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + Error IsEnded(); + Error RetError(); + + BOOL SetType(ObjectType type); + BOOL SetValue(int rank, float value); + BOOL SetString(char *string); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchAlien(); + +protected: + ObjectType m_type; + float m_value; + char m_string[100]; + int m_param; + AutoEggPhase m_phase; + float m_progress; + float m_speed; +}; + + +#endif //_AUTOEGG_H_ diff --git a/src/object/auto/autoenergy.cpp b/src/object/auto/autoenergy.cpp new file mode 100644 index 0000000..023a185 --- /dev/null +++ b/src/object/auto/autoenergy.cpp @@ -0,0 +1,665 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "gauge.h" +#include "window.h" +#include "displaytext.h" +#include "sound.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoenergy.h" + + + +#define ENERGY_POWER 0.4f // Necessary energy for a battery +#define ENERGY_DELAY 12.0f // processing time + + + + +// Object's constructor. + +CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_partiSphere = -1; + Init(); +} + +// Object's destructor. + +CAutoEnergy::~CAutoEnergy() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoEnergy::DeleteObject(BOOL bAll) +{ + CObject* fret; + + if ( m_partiSphere != -1 ) + { + m_particule->DeleteParticule(m_partiSphere); + m_partiSphere = -1; + } + + if ( !bAll ) + { + fret = SearchMetal(); + if ( fret != 0 ) + { + fret->DeleteObject(); // destroys the metal + delete fret; + } + + fret = SearchPower(); + if ( fret != 0 ) + { + fret->DeleteObject(); // destroys the cell + delete fret; + } + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoEnergy::Init() +{ + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; + + m_phase = AENP_WAIT; // waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoEnergy::EventProcess(const Event &event) +{ + CObject* fret; + D3DVECTOR pos, ppos, speed; + FPOINT dim, c, p; + TerrainRes res; + float big; + BOOL bGO; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + pos = m_object->RetPosition(0); + pos.y += 10.0f; + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = -7.0f; + dim.x = Rand()*0.5f+0.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f); + } + } + return TRUE; + } + + UpdateInterface(event.rTime); + EventProgress(event.rTime); + + big = m_object->RetEnergy(); + + res = m_terrain->RetResource(m_object->RetPosition(0)); + if ( res == TR_POWER ) + { + big += event.rTime*0.01f; // recharges the big pile + } + + if ( m_phase == AENP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + bGO = FALSE; + fret = SearchMetal(); // transform metal? + if ( fret != 0 ) + { + if ( fret->RetType() == OBJECT_METAL ) + { + if ( big > ENERGY_POWER ) bGO = TRUE; + } + else + { + if ( !SearchVehicle() ) bGO = TRUE; + } + } + + if ( bGO ) + { + if ( fret->RetType() == OBJECT_METAL ) + { + fret->SetLock(TRUE); // usable metal + CreatePower(); // creates the battery + } + + SetBusy(TRUE); + InitProgressTotal(ENERGY_DELAY); + CAuto::UpdateInterface(); + + pos = m_object->RetPosition(0); + pos.y += 4.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 3.0f; + dim.y = dim.x; + m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE1, ENERGY_DELAY, 0.0f, 0.0f); + + m_phase = AENP_CREATE; + m_progress = 0.0f; + m_speed = 1.0f/ENERGY_DELAY; + } + else + { + if ( rand()%3 == 0 && big > 0.01f ) + { + m_phase = AENP_BLITZ; + m_progress = 0.0f; + m_speed = 1.0f/Rand()*1.0f+1.0f; + } + else + { + m_phase = AENP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + } + } + + if ( m_phase == AENP_BLITZ ) + { + if ( m_progress < 1.0f && big > 0.01f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + pos = m_object->RetPosition(0); + pos.y += 10.0f; + speed.x = (Rand()-0.5f)*1.0f; + speed.z = (Rand()-0.5f)*1.0f; + speed.y = -7.0f; + dim.x = Rand()*0.5f+0.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f); + } + } + else + { + m_phase = AENP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == AENP_CREATE ) + { + if ( m_progress < 1.0f ) + { + fret = SearchMetal(); + if ( fret != 0 ) + { + if ( fret->RetType() == OBJECT_METAL ) + { + big -= event.rTime/ENERGY_DELAY*ENERGY_POWER; + } + else + { + big += event.rTime/ENERGY_DELAY*0.25f; + } + fret->SetZoom(0, 1.0f-m_progress); + } + + fret = SearchPower(); + if ( fret != 0 ) + { + fret->SetZoom(0, m_progress); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + c.x = pos.x; + c.y = pos.z; + p.x = c.x; + p.y = c.y+2.0f; + p = RotatePoint(c, Rand()*PI*2.0f, p); + pos.x = p.x; + pos.z = p.y; + pos.y += 2.5f+Rand()*3.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = Rand()*2.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f); + + pos = m_object->RetPosition(0); + pos.y += 3.0f; + speed.x = (Rand()-0.5f)*30.0f; + speed.z = (Rand()-0.5f)*30.0f; + speed.y = Rand()*20.0f+10.0f; + dim.x = Rand()*0.4f+0.4f; + dim.y = dim.x; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, 2.0f, 50.0f, 1.2f, 1.2f); + + pos = m_object->RetPosition(0); + pos.y += 10.0f; + speed.x = (Rand()-0.5f)*1.5f; + speed.z = (Rand()-0.5f)*1.5f; + speed.y = -6.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f); + + m_sound->Play(SOUND_ENERGY, m_object->RetPosition(0), + 1.0f, 1.0f+Rand()*1.5f); + } + } + else + { + fret = SearchMetal(); + if ( fret != 0 ) + { + m_object->SetPower(0); + fret->DeleteObject(); // destroys the metal + delete fret; + } + + fret = SearchPower(); + if ( fret != 0 ) + { + fret->SetZoom(0, 1.0f); + fret->SetLock(FALSE); // usable battery + fret->SetTruck(m_object); + fret->SetPosition(0, D3DVECTOR(0.0f, 3.0f, 0.0f)); + m_object->SetPower(fret); + + m_displayText->DisplayError(INFO_ENERGY, m_object); + } + + SetBusy(FALSE); + CAuto::UpdateInterface(); + + m_phase = AENP_SMOKE; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + + if ( m_phase == AENP_SMOKE ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y += 17.0f; + pos.x += (Rand()-0.5f)*3.0f; + pos.z += (Rand()-0.5f)*3.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 6.0f+Rand()*6.0f; + dim.x = Rand()*1.5f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + } + else + { + m_phase = AENP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( big < 0.0f ) big = 0.0f; + if ( big > 1.0f ) big = 1.0f; + m_object->SetEnergy(big); // shift the big pile + + return TRUE; +} + + +// Seeking the metal object. + +CObject* CAutoEnergy::SearchMetal() +{ + CObject* pObj; + ObjectType type; + + pObj = m_object->RetPower(); + if ( pObj == 0 ) return 0; + + type = pObj->RetType(); + if ( type == OBJECT_METAL || + type == OBJECT_SCRAP1 || + type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 ) return pObj; + + return 0; +} + +// Search if a vehicle is too close. + +BOOL CAutoEnergy::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType type; + float oRadius, dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, cPos)-oRadius; + + if ( dist < 10.0f ) return TRUE; + } + + return FALSE; +} + +// Create a cell. + +void CAutoEnergy::CreatePower() +{ + CObject* power; + D3DVECTOR pos; + float angle; + + pos = m_object->RetPosition(0); + angle = m_object->RetAngleY(0); + + power = new CObject(m_iMan); + if ( !power->CreateResource(pos, angle, OBJECT_POWER) ) + { + delete power; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return; + } + power->SetLock(TRUE); // battery not yet usable + + pos = power->RetPosition(0); + pos.y += 3.0f; + power->SetPosition(0, pos); +} + +// Seeking the battery during manufacture. + +CObject* CAutoEnergy::SearchPower() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType type; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetLock() ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_POWER ) continue; + + oPos = pObj->RetPosition(0); + if ( oPos.x == cPos.x && + oPos.z == cPos.z ) + { + return pObj; + } + } + + return 0; +} + + +// Returns an error due the state of the automation. + +Error CAutoEnergy::RetError() +{ + CObject* pObj; + ObjectType type; + TerrainRes res; + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + if ( m_phase != AENP_WAIT && + m_phase != AENP_BLITZ ) return ERR_OK; + + res = m_terrain->RetResource(m_object->RetPosition(0)); + if ( res != TR_POWER ) return ERR_ENERGY_NULL; + + if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_ENERGY_LOW; + + pObj = m_object->RetPower(); + if ( pObj == 0 ) return ERR_ENERGY_EMPTY; + type = pObj->RetType(); + if ( type == OBJECT_POWER ) return ERR_OK; + if ( type != OBJECT_METAL && + type != OBJECT_SCRAP1 && + type != OBJECT_SCRAP2 && + type != OBJECT_SCRAP3 ) return ERR_ENERGY_BAD; + + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoEnergy::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*14.5f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 108, EVENT_OBJECT_TYPE); + + return TRUE; +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAutoEnergy::UpdateInterface(float rTime) +{ + CWindow* pw; + CGauge* pg; + + CAuto::UpdateInterface(rTime); + + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY); + if ( pg != 0 ) + { + pg->SetLevel(m_object->RetEnergy()); + } +} + + +// Saves all parameters of the controller. + +BOOL CAutoEnergy::Write(char *line) +{ + char name[100]; + + if ( m_phase == AENP_STOP || + m_phase == AENP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoEnergy::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoEnergyPhase)OpInt(line, "aPhase", AENP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; + + return TRUE; +} diff --git a/src/object/auto/autoenergy.h b/src/object/auto/autoenergy.h new file mode 100644 index 0000000..dd920fb --- /dev/null +++ b/src/object/auto/autoenergy.h @@ -0,0 +1,83 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoenergy.h + +#ifndef _AUTOENERGY_H_ +#define _AUTOENERGY_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoEnergyPhase +{ + AENP_STOP = 1, + AENP_WAIT = 2, + AENP_BLITZ = 3, + AENP_CREATE = 4, + AENP_SMOKE = 5, +}; + + + +class CAutoEnergy : public CAuto +{ +public: + CAutoEnergy(CInstanceManager* iMan, CObject* object); + ~CAutoEnergy(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(float rTime); + + CObject* SearchMetal(); + BOOL SearchVehicle(); + void CreatePower(); + CObject* SearchPower(); + +protected: + AutoEnergyPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastUpdateTime; + float m_lastParticule; + int m_partiSphere; +}; + + +#endif //_AUTOENERGY_H_ diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp new file mode 100644 index 0000000..7fab2fb --- /dev/null +++ b/src/object/auto/autofactory.cpp @@ -0,0 +1,961 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "restext.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "displaytext.h" +#include "robotmain.h" +#include "sound.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autofactory.h" + + + + +// Object's constructor. + +CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_type = OBJECT_MOBILEws; + m_phase = AFP_WAIT; // paused until the first Init () + m_channelSound = -1; +} + +// Object's destructor. + +CAutoFactory::~CAutoFactory() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoFactory::DeleteObject(BOOL bAll) +{ + CObject* fret; + CObject* vehicle; + + if ( !bAll ) + { + fret = SearchFret(); // transform metal? + if ( fret != 0 ) + { + fret->DeleteObject(); // destroys the metal + delete fret; + } + + vehicle = SearchVehicle(); + if ( vehicle != 0 ) + { + vehicle->DeleteObject(); // destroys the vehicle + delete vehicle; + } + } + + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoFactory::Init() +{ + m_phase = AFP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + m_time = 0.0f; + m_lastParticule = 0.0f; + + m_fretPos = m_object->RetPosition(0); + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoFactory::EventProcess(const Event &event) +{ + CObject* fret; + CObject* vehicle; + D3DMATRIX* mat; + CPhysics* physics; + D3DVECTOR pos, speed; + FPOINT dim; + ObjectType type; + float zoom, angle, prog; + int i; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + if ( m_object->RetSelect() ) // factory selected? + { + if ( event.event == EVENT_UPDINTERFACE ) + { + CreateInterface(TRUE); + } + + type = OBJECT_NULL; + if ( event.event == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa; + if ( event.event == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta; + if ( event.event == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa; + if ( event.event == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia; + if ( event.event == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws; + if ( event.event == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts; + if ( event.event == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs; + if ( event.event == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis; + if ( event.event == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc; + if ( event.event == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc; + if ( event.event == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc; + if ( event.event == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic; + if ( event.event == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi; + if ( event.event == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti; + if ( event.event == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi; + if ( event.event == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii; + if ( event.event == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt; + if ( event.event == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc; + if ( event.event == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr; + if ( event.event == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs; + if ( event.event == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa; + + if ( type != OBJECT_NULL ) + { + m_type = type; + + if ( m_phase != AFP_WAIT ) + { + return FALSE; + } + + fret = SearchFret(); // transform metal? + if ( fret == 0 ) + { + m_displayText->DisplayError(ERR_FACTORY_NULL, m_object); + return FALSE; + } + if ( NearestVehicle() ) + { + m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object); + return FALSE; + } + + SetBusy(TRUE); + InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f); + UpdateInterface(); + + fret->SetLock(TRUE); // usable metal + SoundManip(3.0f, 1.0f, 0.5f); + + m_phase = AFP_CLOSE_S; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + return TRUE; + } + } + + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + EventProgress(event.rTime); + + if ( m_phase == AFP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + m_phase = AFP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == AFP_CLOSE_S ) + { + if ( m_progress < 1.0f ) + { + for ( i=0 ; i<9 ; i++ ) + { + zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f; + if ( zoom < 0.30f ) zoom = 0.30f; + if ( zoom > 1.00f ) zoom = 1.00f; + m_object->SetZoomZ( 1+i, zoom); + m_object->SetZoomZ(10+i, zoom); + } + } + else + { + for ( i=0 ; i<9 ; i++ ) + { + m_object->SetZoomZ( 1+i, 1.0f); + m_object->SetZoomZ(10+i, 1.0f); + } + + SoundManip(2.0f, 1.0f, 1.2f); + + m_phase = AFP_CLOSE_T; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == AFP_CLOSE_T ) + { + if ( m_progress < 1.0f ) + { + for ( i=0 ; i<9 ; i++ ) + { + angle = -m_progress*(PI/2.0f)+PI/2.0f; + m_object->SetAngleZ( 1+i, angle); + m_object->SetAngleZ(10+i, -angle); + } + } + else + { + for ( i=0 ; i<9 ; i++ ) + { + m_object->SetAngleZ( 1+i, 0.0f); + m_object->SetAngleZ(10+i, 0.0f); + } + + m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->RetPosition(0), 0.0f, 1.0f, TRUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP); + + m_phase = AFP_BUILD; + m_progress = 0.0f; + m_speed = 1.0f/15.0f; + } + } + + if ( m_phase == AFP_BUILD ) + { + if ( m_progress == 0.0f ) + { + if ( !CreateVehicle() ) + { + fret = SearchFret(); // transform metal? + if ( fret != 0 ) + { + fret->SetLock(FALSE); // metal usable again + } + + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + m_phase = AFP_OPEN_T; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + return TRUE; + } + } + + if ( m_progress < 1.0f ) + { + if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) + { + prog = 1.0f-m_progress*1.5f; + if ( prog < 0.0f ) prog = 0.0f; + } + else + { + prog = 1.0f-m_progress; + } + angle = powf(prog*10.0f, 2.0f)+m_object->RetAngleY(0); + + vehicle = SearchVehicle(); + if ( vehicle != 0 ) + { + vehicle->SetAngleY(0, angle+PI); + vehicle->SetZoom(0, m_progress); + } + + fret = SearchFret(); // transform metal? + if ( fret != 0 ) + { + fret->SetZoom(0, 1.0f-m_progress); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + +#if 0 + pos = m_fretPos; + pos.x += (Rand()-0.5f)*20.0f; + pos.z += (Rand()-0.5f)*20.0f; + pos.y += 1.0f; + speed.x = (Rand()-0.5f)*12.0f; + speed.z = (Rand()-0.5f)*12.0f; + speed.y = Rand()*12.0f; + dim.x = Rand()*12.0f+10.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); +#else + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(-12.0f, 20.0f, -4.0f); // position of chimney + pos = Transform(*mat, pos); + pos.y += 2.0f; + pos.x += (Rand()-0.5f)*2.0f; + pos.z += (Rand()-0.5f)*2.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 6.0f+Rand()*6.0f; + dim.x = Rand()*1.5f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); +#endif + } + } + else + { + m_displayText->DisplayError(INFO_FACTORY, m_object); + SoundManip(2.0f, 1.0f, 1.2f); + + fret = SearchFret(); // transform metal? + if ( fret != 0 ) + { + fret->DeleteObject(); // removes the metal + delete fret; + } + + vehicle = SearchVehicle(); + if ( vehicle != 0 ) + { + physics = vehicle->RetPhysics(); + if ( physics != 0 ) + { + physics->SetFreeze(FALSE); // can move + } + + vehicle->SetLock(FALSE); // vehicle useable +//? vehicle->RetPhysics()->RetBrain()->StartTaskAdvance(16.0f); + vehicle->SetAngleY(0, m_object->RetAngleY(0)+PI); + vehicle->SetZoom(0, 1.0f); + } + + m_main->CreateShortcuts(); + + m_phase = AFP_OPEN_T; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == AFP_OPEN_T ) + { + if ( m_progress < 1.0f ) + { + for ( i=0 ; i<9 ; i++ ) + { + angle = -(1.0f-m_progress)*(PI/2.0f)+PI/2.0f; + m_object->SetAngleZ( 1+i, angle); + m_object->SetAngleZ(10+i, -angle); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_fretPos; + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + pos.y += Rand()*10.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f); + } + } + else + { + for ( i=0 ; i<9 ; i++ ) + { + m_object->SetAngleZ( 1+i, PI/2.0f); + m_object->SetAngleZ(10+i, -PI/2.0f); + } + + SoundManip(3.0f, 1.0f, 0.5f); + + m_phase = AFP_OPEN_S; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + + if ( m_phase == AFP_OPEN_S ) + { + if ( m_progress < 1.0f ) + { + for ( i=0 ; i<9 ; i++ ) + { + zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f; + if ( zoom < 0.30f ) zoom = 0.30f; + if ( zoom > 1.00f ) zoom = 1.00f; + m_object->SetZoomZ( 1+i, zoom); + m_object->SetZoomZ(10+i, zoom); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_fretPos; + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + pos.y += Rand()*10.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f); + } + } + else + { + for ( i=0 ; i<9 ; i++ ) + { + m_object->SetZoomZ( 1+i, 0.30f); + m_object->SetZoomZ(10+i, 0.30f); + } + + SetBusy(FALSE); + UpdateInterface(); + + m_phase = AFP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + return TRUE; +} + + +// Saves all parameters of the controller. + +BOOL CAutoFactory::Write(char *line) +{ + char name[100]; + + if ( m_phase == AFP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller + +BOOL CAutoFactory::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoFactoryPhase)OpInt(line, "aPhase", AFP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + m_fretPos = m_object->RetPosition(0); + + return TRUE; +} + + +//Seeks the cargo. + +CObject* CAutoFactory::SearchFret() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_METAL ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, m_fretPos); + + if ( dist < 8.0f ) return pObj; + } + + return 0; +} + +// Search if a vehicle is too close. + +BOOL CAutoFactory::NearestVehicle() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType type; + float oRadius, dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, cPos)-oRadius; + + if ( dist < 10.0f ) return TRUE; + } + + return FALSE; +} + + +// Creates a vehicle. + +BOOL CAutoFactory::CreateVehicle() +{ + CObject* vehicle; + D3DMATRIX* mat; + CPhysics* physics; + D3DVECTOR pos; + float angle; + char* name; + int i; + + angle = m_object->RetAngleY(0); + + mat = m_object->RetWorldMatrix(0); + if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) + { + pos = D3DVECTOR(2.0f, 0.0f, 0.0f); + } + else + { + pos = D3DVECTOR(4.0f, 0.0f, 0.0f); + } + pos = Transform(*mat, pos); + + vehicle = new CObject(m_iMan); + if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, FALSE, FALSE) ) + { + delete vehicle; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return FALSE; + } + vehicle->UpdateMapping(); + vehicle->SetLock(TRUE); // not usable + vehicle->SetRange(30.0f); + + physics = vehicle->RetPhysics(); + if ( physics != 0 ) + { + physics->SetFreeze(TRUE); // it doesn't move + } + + for ( i=0 ; i<10 ; i++ ) + { + name = m_main->RetNewScriptName(m_type, i); + if ( name == 0 ) break; + vehicle->ReadProgram(i, name); + } + + return TRUE; +} + +// Seeking the vehicle during manufacture. + +CObject* CAutoFactory::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetLock() ) continue; + + type = pObj->RetType(); + if ( type != m_type ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, m_fretPos); + + if ( dist < 8.0f ) return pObj; + } + + return 0; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoFactory::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = 0.0f; + pos.y = oy+sy*2.6f; + ddim.x = 138.0f/640.0f; + ddim.y = 222.0f/480.0f; + pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*8.2f; + pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*7.1f; + pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*6.0f; + pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*4.9f; + pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*3.8f; + pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*2.7f; + pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 101, EVENT_OBJECT_TYPE); + + UpdateInterface(); + return TRUE; +} + +// Updates the status of all interface buttons. + +void CAutoFactory::UpdateInterface() +{ + CWindow* pw; + + if ( !m_object->RetSelect() ) return; + + CAuto::UpdateInterface(); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + + UpdateButton(pw, EVENT_OBJECT_FACTORYwa, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYta, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYfa, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYia, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYws, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYts, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYfs, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYis, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYwc, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYtc, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYfc, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYic, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYwi, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy); +} + +// Updates the status of one interface button. + +void CAutoFactory::UpdateButton(CWindow *pw, EventMsg event, BOOL bBusy) +{ + BOOL bEnable = TRUE; + + EnableInterface(pw, event, !bBusy); + + if ( event == EVENT_OBJECT_FACTORYta ) + { + bEnable = g_researchDone&RESEARCH_TANK; + } + if ( event == EVENT_OBJECT_FACTORYfa ) + { + bEnable = g_researchDone&RESEARCH_FLY; + } + if ( event == EVENT_OBJECT_FACTORYia ) + { + bEnable = g_researchDone&RESEARCH_iPAW; + } + + if ( event == EVENT_OBJECT_FACTORYws ) + { + bEnable = g_researchDone&RESEARCH_SNIFFER; + } + if ( event == EVENT_OBJECT_FACTORYts ) + { + bEnable = ( (g_researchDone&RESEARCH_SNIFFER) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYfs ) + { + bEnable = ( (g_researchDone&RESEARCH_SNIFFER) && + (g_researchDone&RESEARCH_FLY) ); + } + if ( event == EVENT_OBJECT_FACTORYis ) + { + bEnable = ( (g_researchDone&RESEARCH_SNIFFER) && + (g_researchDone&RESEARCH_iPAW) ); + } + + if ( event == EVENT_OBJECT_FACTORYwc ) + { + bEnable = g_researchDone&RESEARCH_CANON; + } + if ( event == EVENT_OBJECT_FACTORYtc ) + { + bEnable = ( (g_researchDone&RESEARCH_CANON) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYfc ) + { + bEnable = ( (g_researchDone&RESEARCH_CANON) && + (g_researchDone&RESEARCH_FLY) ); + } + if ( event == EVENT_OBJECT_FACTORYic ) + { + bEnable = ( (g_researchDone&RESEARCH_CANON) && + (g_researchDone&RESEARCH_iPAW) ); + } + + if ( event == EVENT_OBJECT_FACTORYwi ) + { + bEnable = g_researchDone&RESEARCH_iGUN; + } + if ( event == EVENT_OBJECT_FACTORYti ) + { + bEnable = ( (g_researchDone&RESEARCH_iGUN) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYfi ) + { + bEnable = ( (g_researchDone&RESEARCH_iGUN) && + (g_researchDone&RESEARCH_FLY) ); + } + if ( event == EVENT_OBJECT_FACTORYii ) + { + bEnable = ( (g_researchDone&RESEARCH_iGUN) && + (g_researchDone&RESEARCH_iPAW) ); + } + + if ( event == EVENT_OBJECT_FACTORYrt ) + { + bEnable = ( (g_researchDone&RESEARCH_THUMP) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYrc ) + { + bEnable = ( (g_researchDone&RESEARCH_PHAZER) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYrr ) + { + bEnable = ( (g_researchDone&RESEARCH_RECYCLER) && + (g_researchDone&RESEARCH_TANK) ); + } + if ( event == EVENT_OBJECT_FACTORYrs ) + { + bEnable = ( (g_researchDone&RESEARCH_SHIELD) && + (g_researchDone&RESEARCH_TANK) ); + } + + if ( event == EVENT_OBJECT_FACTORYsa ) + { + bEnable = g_researchDone&RESEARCH_SUBM; + } + + DeadInterface(pw, event, bEnable); +} + +// Plays the sound of the manipulator arm. + +void CAutoFactory::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, TRUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + diff --git a/src/object/auto/autofactory.h b/src/object/auto/autofactory.h new file mode 100644 index 0000000..bcfc43e --- /dev/null +++ b/src/object/auto/autofactory.h @@ -0,0 +1,85 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autofactory.h + +#ifndef _AUTOFACTORY_H_ +#define _AUTOFACTORY_H_ + + +#include "auto.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoFactoryPhase +{ + AFP_WAIT = 1, // expected metal + AFP_CLOSE_S = 2, // closes doors (shift) + AFP_CLOSE_T = 3, // closes doors (turn) + AFP_BUILD = 4, // building the vehicle + AFP_OPEN_T = 5, // opens the doors (turn) + AFP_OPEN_S = 6, // opens the doors (shift) + AFP_ADVANCE = 7, // advance at the door +}; + + + +class CAutoFactory : public CAuto +{ +public: + CAutoFactory(CInstanceManager* iMan, CObject* object); + ~CAutoFactory(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(); + void UpdateButton(CWindow *pw, EventMsg event, BOOL bBusy); + + CObject* SearchFret(); + BOOL NearestVehicle(); + BOOL CreateVehicle(); + CObject* SearchVehicle(); + + void SoundManip(float time, float amplitude, float frequency); + +protected: + AutoFactoryPhase m_phase; + float m_progress; + float m_speed; + float m_lastParticule; + D3DVECTOR m_fretPos; + int m_channelSound; +}; + + +#endif //_AUTOFACTORY_H_ diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp new file mode 100644 index 0000000..5cd4bf2 --- /dev/null +++ b/src/object/auto/autoflag.cpp @@ -0,0 +1,178 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "auto.h" +#include "autoflag.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members + + +#if ADJUST_ANGLE +static float g_flag1 = 6.00f; +static float g_flag2 = 0.10f; +static float g_flag3 = 2.00f; +#endif + + +// Object's constructor. + +CAutoFlag::CAutoFlag(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoFlag::~CAutoFlag() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoFlag::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoFlag::Init() +{ + D3DVECTOR wind; + float angle; + + m_time = 0.0f; + m_param = 0; + m_progress = 0.0f; + + wind = m_terrain->RetWind(); + angle = RotateAngle(wind.x, -wind.z); + m_object->SetAngleY(0, angle); // directs the flag in the wind + + m_strong = Length(wind); +} + + +// Beginning of an action (1 = shakes). + +void CAutoFlag::Start(int param) +{ + if ( m_param == 0 ) + { + m_param = param; + m_progress = 0.0f; + } +} + + +// Management of an event. + +BOOL CAutoFlag::EventProcess(const Event &event) +{ + float angle; + int i; + + CAuto::EventProcess(event); + +#if ADJUST_ANGLE + if ( event.event == EVENT_KEYDOWN ) + { + if ( event.param == 'E' ) g_flag1 += 0.1f; + if ( event.param == 'D' ) g_flag1 -= 0.1f; + if ( event.param == 'R' ) g_flag2 += 0.1f; + if ( event.param == 'F' ) g_flag2 -= 0.1f; + if ( event.param == 'T' ) g_flag3 += 0.1f; + if ( event.param == 'G' ) g_flag3 -= 0.1f; + } +#endif + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + if ( m_param == 1 ) // shakes? + { + m_progress += event.rTime*(1.0f/2.0f); + if ( m_progress < 1.0f ) + { + angle = sinf(m_progress*PI*8.0f)*0.3f*(1.0f-m_progress); + m_object->SetAngleX(0, angle); + angle = sinf(m_progress*PI*4.0f)*0.3f*(1.0f-m_progress); + m_object->SetAngleZ(0, angle); + } + else + { + m_object->SetAngleX(0, 0.0f); + m_object->SetAngleZ(0, 0.0f); + m_param = 0; + m_progress = 0.0f; + } + } + + if ( m_strong == 0.0f ) return TRUE; // no wind? + + for ( i=0 ; i<4 ; i++ ) + { +#if ADJUST_ANGLE + angle = sinf(m_time*g_flag1+i*2.0f)*((i+g_flag3)*g_flag2); +#else + angle = sinf(m_time*6.0f+i*2.0f)*((i+2.0f)*0.1f); +#endif + m_object->SetAngleY(1+i, angle); + } + +#if ADJUST_ANGLE + char s[100]; + sprintf(s, "a=%.2f b=%.2f c=%.2f", g_flag1, g_flag2, g_flag3); + m_engine->SetInfoText(4, s); +#endif + return TRUE; +} + + +// Returns an error due the state of the automation + +Error CAutoFlag::RetError() +{ + return ERR_OK; +} + + diff --git a/src/object/auto/autoflag.h b/src/object/auto/autoflag.h new file mode 100644 index 0000000..4ef0fe4 --- /dev/null +++ b/src/object/auto/autoflag.h @@ -0,0 +1,58 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoflag.h + +#ifndef _AUTOFLAG_H_ +#define _AUTOFLAG_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +class CAutoFlag : public CAuto +{ +public: + CAutoFlag(CInstanceManager* iMan, CObject* object); + ~CAutoFlag(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + Error RetError(); + +protected: + +protected: + float m_strong; + int m_param; + float m_progress; +}; + + +#endif //_AUTOFLAG_H_ diff --git a/src/object/auto/autohuston.cpp b/src/object/auto/autohuston.cpp new file mode 100644 index 0000000..ad66702 --- /dev/null +++ b/src/object/auto/autohuston.cpp @@ -0,0 +1,315 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "auto.h" +#include "autohuston.h" + + + + +// Object's constructor. + +CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + D3DVECTOR pos; + int i; + + CAuto::CAuto(iMan, object); + + for ( i=0 ; iRetPosition(0); + m_lens[0].type = PARTISELR; + m_lens[1].type = PARTISELR; + m_lens[2].type = PARTISELR; + m_lens[3].type = PARTISELR; + m_lens[0].pos = pos+D3DVECTOR(0.0f+13.0f, 34.0f, 30.0f ); + m_lens[1].pos = pos+D3DVECTOR(0.0f-13.0f, 34.0f, 30.0f ); + m_lens[2].pos = pos+D3DVECTOR(0.0f , 34.0f, 30.0f+13.0f); + m_lens[3].pos = pos+D3DVECTOR(0.0f , 34.0f, 30.0f-13.0f); + m_lens[0].dim = 4.0f; + m_lens[1].dim = 4.0f; + m_lens[2].dim = 4.0f; + m_lens[3].dim = 4.0f; + m_lens[0].total = 1.0f; + m_lens[1].total = 1.0f; + m_lens[2].total = 1.0f; + m_lens[3].total = 1.0f; + m_lens[0].off = 0.4f; + m_lens[1].off = 0.4f; + m_lens[2].off = 0.4f; + m_lens[3].off = 0.4f; + + // Part under the radar. + i = 4; + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 9.9f, 40.1f); + m_lens[i].dim = 1.8f; + m_lens[i].total = 0.4f; + m_lens[i].off = 0.2f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 7.2f, 34.8f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.7f; + m_lens[i].off = 0.3f; + i ++; + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 34.3f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.7f; + m_lens[i].off = 0.3f; + i ++; + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 33.4f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.0f; + m_lens[i].off = 0.0f; + i ++; + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 33.0f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 1.0f; + m_lens[i].off = 0.5f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 8.5f, 14.0f); + m_lens[i].dim = 1.2f; + m_lens[i].total = 0.8f; + m_lens[i].off = 0.2f; + i ++; + + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(4.0f, 6.0f, 8.6f); + m_lens[i].dim = 1.0f; + m_lens[i].total = 0.9f; + m_lens[i].off = 0.7f; + i ++; + + // Part with three windows. + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 9.9f, -19.9f); + m_lens[i].dim = 1.0f; + m_lens[i].total = 0.6f; + m_lens[i].off = 0.3f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 7.2f, 34.8f-60.0f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.7f; + m_lens[i].off = 0.3f; + i ++; + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 34.3f-60.0f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.0f; + m_lens[i].off = 0.0f; + i ++; + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 33.4f-60.0f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.6f; + m_lens[i].off = 0.4f; + i ++; + m_lens[i].type = PARTISELR; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 6.5f, 33.0f-60.0f); + m_lens[i].dim = 0.4f; + m_lens[i].total = 0.8f; + m_lens[i].off = 0.2f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-6.5f, 13.5f, -37.0f); + m_lens[i].dim = 1.0f; + m_lens[i].total = 0.0f; + m_lens[i].off = 0.0f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 12.2f, -39.8f); + m_lens[i].dim = 1.8f; + m_lens[i].total = 1.5f; + m_lens[i].off = 0.5f; + i ++; + + m_lens[i].type = PARTISELY; + m_lens[i].pos = pos+D3DVECTOR(-7.0f, 8.5f, -47.0f); + m_lens[i].dim = 0.6f; + m_lens[i].total = 0.7f; + m_lens[i].off = 0.5f; + i ++; + + m_lensTotal = i; + + Init(); +} + +// Object's destructor. + +CAutoHuston::~CAutoHuston() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoHuston::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoHuston::Init() +{ + m_time = 0.0f; + + m_progress = 0.0f; + m_speed = 1.0f/2.0f; +} + + +// Start the object. + +void CAutoHuston::Start(int param) +{ +} + + +// Management of an event. + +BOOL CAutoHuston::EventProcess(const Event &event) +{ + D3DVECTOR speed; + FPOINT dim; + float angle; + int i; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + angle = -m_time*1.0f; + m_object->SetAngleY(1, angle); // rotates the radar + angle = sinf(m_time*4.0f)*0.3f; + m_object->SetAngleX(2, angle); + + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + + // Flashes the keys. + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + for ( i=0 ; iDeleteParticule(m_lens[i].parti); + m_lens[i].parti = -1; + } + } + else + { + if ( m_lens[i].parti == -1 ) + { + dim.x = m_lens[i].dim; + dim.y = dim.x; + m_lens[i].parti = m_particule->CreateParticule(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f); + } + } + } + + return TRUE; +} + +// Stops the controller. + +BOOL CAutoHuston::Abort() +{ + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoHuston::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 115, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Returns an error due to state of the automation. + +Error CAutoHuston::RetError() +{ + return ERR_OK; +} + diff --git a/src/object/auto/autohuston.h b/src/object/auto/autohuston.h new file mode 100644 index 0000000..0611eb2 --- /dev/null +++ b/src/object/auto/autohuston.h @@ -0,0 +1,77 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autohuston.h + +#ifndef _AUTOHUSTON_H_ +#define _AUTOHUSTON_H_ + + +#include "auto.h" +#include "particule.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +typedef struct +{ + int parti; + ParticuleType type; + D3DVECTOR pos; + float dim; + float total; + float off; +} +HustonLens; + + +#define HUSTONMAXLENS 20 + + +class CAutoHuston : public CAuto +{ +public: + CAutoHuston(CInstanceManager* iMan, CObject* object); + ~CAutoHuston(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + BOOL Abort(); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + +protected: + +protected: + float m_progress; + float m_speed; + HustonLens m_lens[HUSTONMAXLENS]; + int m_lensTotal; +}; + + +#endif //_AUTOHUSTON_H_ diff --git a/src/object/auto/autoinfo.cpp b/src/object/auto/autoinfo.cpp new file mode 100644 index 0000000..e9708e0 --- /dev/null +++ b/src/object/auto/autoinfo.cpp @@ -0,0 +1,537 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "list.h" +#include "window.h" +#include "sound.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoinfo.h" + + + + +// Object's constructor. + +CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoInfo::~CAutoInfo() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoInfo::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoInfo::Init() +{ + m_phase = AIP_WAIT; + m_time = 0.0f; + m_timeVirus = 0.0f; + m_bLastVirus = FALSE; + + CAuto::Init(); +} + + +// Start a emission. + +void CAutoInfo::Start(int param) +{ + D3DVECTOR pos, speed; + FPOINT dim; + + if ( param == 0 ) // instruction "receive" ? + { + m_phase = AIP_EMETTE; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + else if ( param == 2 ) // instruction "send" ? + { + m_phase = AIP_RECEIVE; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + else + { + m_phase = AIP_ERROR; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + + m_lastParticule = 0; + m_goal = m_object->RetPosition(0); + + if ( m_phase == AIP_EMETTE ) + { + pos = m_goal; + pos.y += 9.5f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 30.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISPHERE4, 1.5f, 0.0f, 0.0f); + + m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f); + } + if ( m_phase == AIP_RECEIVE ) + { + pos = m_goal; + pos.y += 9.5f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 50.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISPHERE6, 1.5f, 0.0f, 0.0f); + + m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f); + } + if ( m_phase == AIP_ERROR ) + { + m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f); + } +} + + +// Management of an event. + +BOOL CAutoInfo::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed; + FPOINT dim; + float duration, angle, rTime; + int i; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + angle = m_object->RetAngleY(1); + angle += Rand()*0.3f; + m_object->SetAngleY(1, angle); + + m_object->SetAngleX(2, (Rand()-0.5f)*0.3f); + m_object->SetAngleX(4, (Rand()-0.5f)*0.3f); + m_object->SetAngleX(6, (Rand()-0.5f)*0.3f); + + m_object->SetAngleZ(2, (Rand()-0.5f)*0.3f); + m_object->SetAngleZ(4, (Rand()-0.5f)*0.3f); + m_object->SetAngleZ(6, (Rand()-0.5f)*0.3f); + + UpdateListVirus(); + } + m_bLastVirus = TRUE; + return TRUE; + } + else + { + if ( m_bLastVirus ) + { + m_bLastVirus = FALSE; + UpdateList(); // normally returns the list + } + else + { + if ( m_object->RetInfoUpdate() ) + { + UpdateList(); // updates the list + } + } + } + + UpdateInterface(event.rTime); + + rTime = event.rTime; + + if ( m_phase == AIP_EMETTE ) // instruction "receive" ? + { + if ( m_progress < 0.5f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<4 ; i++ ) + { + pos = m_goal; + pos.y += 9.5f; + speed.x = (Rand()-0.5f)*50.0f; + speed.z = (Rand()-0.5f)*50.0f; + speed.y = (Rand()-0.5f)*50.0f; + speed *= 0.5f+m_progress*0.5f; + dim.x = 0.6f; + dim.y = dim.x; + duration = Rand()*0.5f+0.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + if ( m_progress < 1.0f ) + { + m_progress += rTime*m_speed; + + m_object->SetAngleZ(2, m_progress*2.0f*PI); + m_object->SetAngleZ(4, m_progress*2.0f*PI); + m_object->SetAngleZ(6, m_progress*2.0f*PI); + } + else + { + m_phase = AIP_WAIT; + + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(4, 0.0f); + m_object->SetAngleX(6, 0.0f); + + m_object->SetAngleZ(2, 0.0f); + m_object->SetAngleZ(4, 0.0f); + m_object->SetAngleZ(6, 0.0f); + } + } + + if ( m_phase == AIP_RECEIVE ) // instruction "send" ? + { + if ( m_progress < 0.5f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<4 ; i++ ) + { + pos = m_goal; + pos.y += 9.5f; + speed = pos; + pos.x += (Rand()-0.5f)*40.0f; + pos.y += (Rand()-0.5f)*40.0f; + pos.z += (Rand()-0.5f)*40.0f; + speed = (speed-pos)*1.0f; +//? speed *= 0.5f+m_progress*0.5f; + dim.x = 0.6f; + dim.y = dim.x; + duration = Rand()*0.5f+0.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + if ( m_progress < 1.0f ) + { + m_progress += rTime*m_speed; + + m_object->SetAngleZ(2, m_progress*2.0f*PI); + m_object->SetAngleZ(4, m_progress*2.0f*PI); + m_object->SetAngleZ(6, m_progress*2.0f*PI); + } + else + { + m_phase = AIP_WAIT; + + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(4, 0.0f); + m_object->SetAngleX(6, 0.0f); + + m_object->SetAngleZ(2, 0.0f); + m_object->SetAngleZ(4, 0.0f); + m_object->SetAngleZ(6, 0.0f); + } + } + + if ( m_phase == AIP_ERROR ) + { + if ( m_progress < 0.5f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_goal; + speed.x = (Rand()-0.5f)*5.0f; + speed.z = (Rand()-0.5f)*5.0f; + speed.y = 5.0f+Rand()*5.0f; + dim.x = 5.0f+Rand()*5.0f; + dim.y = dim.x; + duration = Rand()*0.5f+0.5f; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 4.0f); + } + + if ( m_progress < 1.0f ) + { + m_progress += rTime*m_speed; + rTime = 0.0f; // stops the rotation + + if ( m_progress < 0.5f ) + { + angle = m_progress/0.5f; + } + else + { + angle = 1.0f-(m_progress-0.5f)/0.5f; + } + m_object->SetAngleX(2, angle*0.5f); + m_object->SetAngleX(4, angle*0.5f); + m_object->SetAngleX(6, angle*0.5f); + + m_object->SetAngleZ(2, (Rand()-0.5f)*0.2f); + m_object->SetAngleZ(4, (Rand()-0.5f)*0.2f); + m_object->SetAngleZ(6, (Rand()-0.5f)*0.2f); + } + else + { + m_phase = AIP_WAIT; + + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(4, 0.0f); + m_object->SetAngleX(6, 0.0f); + + m_object->SetAngleZ(2, 0.0f); + m_object->SetAngleZ(4, 0.0f); + m_object->SetAngleZ(6, 0.0f); + } + } + + angle = m_object->RetAngleY(1); + angle += rTime*0.5f; + m_object->SetAngleY(1, angle); + + m_object->SetAngleX(3, sinf(m_time*6.0f+PI*0.0f/3.0f)*0.3f); + m_object->SetAngleX(5, sinf(m_time*6.0f+PI*2.0f/3.0f)*0.3f); + m_object->SetAngleX(7, sinf(m_time*6.0f+PI*4.0f/3.0f)*0.3f); + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoInfo::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoInfo::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + CList* pl; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.0f; + ddim.x = 160.0f/640.0f; + ddim.y = 66.0f/480.0f; + pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f); + pl->SetSelectCap(FALSE); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE); + + UpdateList(); + return TRUE; +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAutoInfo::UpdateInterface(float rTime) +{ + CAuto::UpdateInterface(rTime); +} + + +// Updates the contents of the list. + +void CAutoInfo::UpdateList() +{ + CWindow* pw; + CList* pl; + Info info; + int total, i; + char text[100]; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO); + if ( pl == 0 ) return; + + pl->Flush(); + total = m_object->RetInfoTotal(); + if ( total == 0 ) + { + pl->ClearState(STATE_ENABLE); + } + else + { + pl->SetState(STATE_ENABLE); + + for ( i=0 ; iRetInfo(i); + sprintf(text, "%s = %.2f", info.name, info.value); + pl->SetName(i, text); + } + } + + m_object->SetInfoUpdate(FALSE); +} + +// Updates the content of contaminating the list. + +void CAutoInfo::UpdateListVirus() +{ + CWindow* pw; + CList* pl; + int i, j, max; + char text[100]; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO); + if ( pl == 0 ) return; + + pl->SetState(STATE_ENABLE); + + pl->Flush(); + for ( i=0 ; i<4 ; i++ ) + { + max = (int)(2.0f+Rand()*10.0f); + for ( j=0 ; jSetName(i, text); + } +} + + +// Saves all parameters of the controller. + +BOOL CAutoInfo::Write(char *line) +{ + char name[100]; + + if ( m_phase == AIP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoInfo::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoInfoPhase)OpInt(line, "aPhase", AIP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autoinfo.h b/src/object/auto/autoinfo.h new file mode 100644 index 0000000..28fc9ab --- /dev/null +++ b/src/object/auto/autoinfo.h @@ -0,0 +1,80 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoinfo.h + +#ifndef _AUTOINFO_H_ +#define _AUTOINFO_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoInfoPhase +{ + AIP_WAIT = 1, + AIP_EMETTE = 2, + AIP_RECEIVE = 3, + AIP_ERROR = 4, +}; + + + +class CAutoInfo : public CAuto +{ +public: + CAutoInfo(CInstanceManager* iMan, CObject* object); + ~CAutoInfo(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(float rTime); + void UpdateList(); + void UpdateListVirus(); + +protected: + AutoInfoPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + D3DVECTOR m_goal; + BOOL m_bLastVirus; +}; + + +#endif //_AUTOINFO_H_ diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp new file mode 100644 index 0000000..1bcd11e --- /dev/null +++ b/src/object/auto/autojostle.cpp @@ -0,0 +1,167 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "list.h" +#include "window.h" +#include "sound.h" +#include "auto.h" +#include "autojostle.h" + + + + +// Object's constructor. + +CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoJostle::~CAutoJostle() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoJostle::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoJostle::Init() +{ + m_time = 0.0f; + m_error = ERR_CONTINUE; + + CAuto::Init(); +} + + +// Start an emission. + +void CAutoJostle::Start(int param, float force) +{ + ObjectType type; + + if ( force < 0.0f ) force = 0.0f; + if ( force > 1.0f ) force = 1.0f; + + m_force = force; + m_progress = 0.0f; + m_speed = 1.0f/(0.5f+force*1.0f); // 0.5 .. 1.5 + m_time = 0.0f; + m_error = ERR_CONTINUE; + + type = m_object->RetType(); + if ( type >= OBJECT_PLANT5 && + type <= OBJECT_PLANT7 ) // clover? + { + m_force *= 3.0f; + } +} + + +// Management of an event. + +BOOL CAutoJostle::EventProcess(const Event &event) +{ + D3DVECTOR dir; + float factor, angle, zoom; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + if ( m_progress < 1.0f ) + { + m_progress += event.rTime*m_speed; + + if ( m_progress < 0.5f ) + { + factor = m_progress/0.5f; + } + else + { + factor = 2.0f-m_progress/0.5f; + } + factor *= m_force; + + dir.x = sinf(m_progress*PI*4.0f); + dir.z = cosf(m_progress*PI*4.0f); + + angle = sinf(m_time*10.0f)*factor*0.04f; + m_object->SetAngleX(0, angle*dir.z); + m_object->SetAngleZ(0, angle*dir.x); + + zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f; + m_object->SetZoomX(0, zoom); + zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f; + m_object->SetZoomY(0, zoom); + zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f; + m_object->SetZoomZ(0, zoom); + } + else + { + m_object->SetAngleX(0, 0.0f); + m_object->SetAngleZ(0, 0.0f); + m_object->SetZoom(0, D3DVECTOR(1.0f, 1.0f, 1.0f)); + m_error = ERR_STOP; + } + + return TRUE; +} + + +// Indicates whether the controller has completed its activity. + +Error CAutoJostle::IsEnded() +{ + return m_error; +} + + diff --git a/src/object/auto/autojostle.h b/src/object/auto/autojostle.h new file mode 100644 index 0000000..18027a0 --- /dev/null +++ b/src/object/auto/autojostle.h @@ -0,0 +1,60 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autojostle.h + +#ifndef _AUTOJOSTLE_H_ +#define _AUTOJOSTLE_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +class CAutoJostle : public CAuto +{ +public: + CAutoJostle(CInstanceManager* iMan, CObject* object); + ~CAutoJostle(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param, float force); + BOOL EventProcess(const Event &event); + Error IsEnded(); + +protected: + +protected: + float m_force; + float m_progress; + float m_speed; + float m_lastParticule; + Error m_error; +}; + + +#endif //_AUTOJOSTLE_H_ diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp new file mode 100644 index 0000000..98c0f45 --- /dev/null +++ b/src/object/auto/autokid.cpp @@ -0,0 +1,222 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "camera.h" +#include "object.h" +#include "sound.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autokid.h" + + + + +// Object's constructor. + +CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_soundChannel = -1; + Init(); +} + +// Object's constructor. + +CAutoKid::~CAutoKid() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoKid::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoKid::Init() +{ + D3DVECTOR pos; + + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + m_lastParticule = 0.0f; + + if ( m_type == OBJECT_TEEN36 ) // trunk ? + { + pos = m_object->RetPosition(0); + m_speed = 1.0f/(1.0f+(Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f)); + m_progress = Mod(pos.x/10.0f, 1.0f); + } + + if ( m_type == OBJECT_TEEN37 ) // boat? + { + pos = m_object->RetPosition(0); + m_speed = 1.0f/(1.0f+(Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f; + m_progress = Mod(pos.x/10.0f, 1.0f); + } + + if ( m_type == OBJECT_TEEN38 ) // fan? + { + if ( m_soundChannel == -1 ) + { +//? m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.5f, TRUE); + m_bSilent = FALSE; + } + } +} + + +// Management of an event. + +BOOL CAutoKid::EventProcess(const Event &event) +{ + D3DVECTOR vib, pos, speed; + FPOINT dim; + + CAuto::EventProcess(event); + + if ( m_soundChannel != -1 ) + { + if ( m_engine->RetPause() ) + { + if ( !m_bSilent ) + { + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.1f, SOPER_CONTINUE); + m_bSilent = TRUE; + } + } + else + { + if ( m_bSilent ) + { + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 0.1f, SOPER_CONTINUE); + m_bSilent = FALSE; + } + } + } + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + + if ( m_type == OBJECT_TEEN36 ) // trunk? + { + vib.x = 0.0f; + vib.y = sinf(m_progress)*1.0f; + vib.z = 0.0f; + m_object->SetLinVibration(vib); + + vib.x = 0.0f; + vib.y = 0.0f; + vib.z = sinf(m_progress*0.5f)*0.05f; + m_object->SetCirVibration(vib); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y = m_water->RetLevel()+1.0f; + pos.x += (Rand()-0.5f)*50.0f; + pos.z += (Rand()-0.5f)*50.0f; + speed.y = 0.0f; + speed.x = 0.0f; + speed.z = 0.0f; + dim.x = 50.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f); + } + } + + if ( m_type == OBJECT_TEEN37 ) // boat? + { + vib.x = 0.0f; + vib.y = sinf(m_progress)*1.0f; + vib.z = 0.0f; + m_object->SetLinVibration(vib); + + vib.x = 0.0f; + vib.y = 0.0f; + vib.z = sinf(m_progress*0.5f)*0.15f; + m_object->SetCirVibration(vib); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y = m_water->RetLevel()+1.0f; + pos.x += (Rand()-0.5f)*20.0f; + pos.z += (Rand()-0.5f)*20.0f; + speed.y = 0.0f; + speed.x = 0.0f; + speed.z = 0.0f; + dim.x = 20.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f); + } + } + + if ( m_type == OBJECT_TEEN38 ) // fan? + { + m_object->SetAngleY(1, sinf(m_progress*0.6f)*0.4f); + m_object->SetAngleX(2, m_progress*5.0f); + } + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoKid::RetError() +{ + return ERR_OK; +} + + diff --git a/src/object/auto/autokid.h b/src/object/auto/autokid.h new file mode 100644 index 0000000..dc5305b --- /dev/null +++ b/src/object/auto/autokid.h @@ -0,0 +1,59 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autokid.h + +#ifndef _AUTOKID_H_ +#define _AUTOKID_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +class CAutoKid : public CAuto +{ +public: + CAutoKid(CInstanceManager* iMan, CObject* object); + ~CAutoKid(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + +protected: + +protected: + float m_speed; + float m_progress; + float m_lastParticule; + int m_soundChannel; + BOOL m_bSilent; +}; + + +#endif //_AUTOKID_H_ diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp new file mode 100644 index 0000000..ce6214c --- /dev/null +++ b/src/object/auto/autolabo.cpp @@ -0,0 +1,629 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "displaytext.h" +#include "sound.h" +#include "robotmain.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autolabo.h" + + + +#define LABO_DELAY 20.0f // duration of the analysis + + + + +// Object's constructor. + +CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + int i; + + CAuto::CAuto(iMan, object); + + for ( i=0 ; i<3 ; i++ ) + { + m_partiRank[i] = -1; + } + m_partiSphere = -1; + + m_soundChannel = -1; + Init(); +} + +// Object's destructor. + +CAutoLabo::~CAutoLabo() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoLabo::DeleteObject(BOOL bAll) +{ + int i; + + for ( i=0 ; i<3 ; i++ ) + { + if ( m_partiRank[i] != -1 ) + { + m_particule->DeleteParticule(m_partiRank[i]); + m_partiRank[i] = -1; + } + } + + if ( m_partiSphere != -1 ) + { + m_particule->DeleteParticule(m_partiSphere); + m_partiSphere = -1; + } + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoLabo::Init() +{ + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + m_phase = ALAP_WAIT; // waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoLabo::EventProcess(const Event &event) +{ + CObject* power; + D3DVECTOR pos, goal, speed; + FPOINT dim, rot; + float angle; + int i; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + if ( event.event == EVENT_UPDINTERFACE ) + { + if ( m_object->RetSelect() ) CreateInterface(TRUE); + } + + if ( m_object->RetSelect() && // center selected? + (event.event == EVENT_OBJECT_RiPAW || + event.event == EVENT_OBJECT_RiGUN) ) + { + if ( m_phase != ALAP_WAIT ) + { + return FALSE; + } + + m_research = event.event; + + if ( TestResearch(m_research) ) + { + m_displayText->DisplayError(ERR_LABO_ALREADY, m_object); + return FALSE; + } + + power = m_object->RetPower(); + if ( power == 0 ) + { + m_displayText->DisplayError(ERR_LABO_NULL, m_object); + return FALSE; + } + if ( power->RetType() != OBJECT_BULLET ) + { + m_displayText->DisplayError(ERR_LABO_BAD, m_object); + return FALSE; + } + + SetBusy(TRUE); + InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f); + UpdateInterface(); + + power->SetLock(TRUE); // ball longer usable + + SoundManip(1.0f, 1.0f, 1.0f); + m_phase = ALAP_OPEN1; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + return TRUE; + } + + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + EventProgress(event.rTime); + + if ( m_phase == ALAP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + m_phase = ALAP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == ALAP_OPEN1 ) + { + if ( m_progress < 1.0f ) + { + angle = 80.0f-(35.0f*m_progress); + m_object->SetAngleZ(3, angle*PI/180.0f); + m_object->SetAngleZ(4, angle*PI/180.0f); + m_object->SetAngleZ(5, angle*PI/180.0f); + } + else + { + m_object->SetAngleZ(3, 45.0f*PI/180.0f); + m_object->SetAngleZ(4, 45.0f*PI/180.0f); + m_object->SetAngleZ(5, 45.0f*PI/180.0f); + + SoundManip(1.5f, 1.0f, 0.7f); + m_phase = ALAP_OPEN2; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ALAP_OPEN2 ) + { + if ( m_progress < 1.0f ) + { + pos.x = -9.0f; + pos.y = 3.0f+m_progress*10.0f; + pos.z = 0.0f; + m_object->SetPosition(1, pos); + } + else + { + m_object->SetPosition(1, D3DVECTOR(-9.0f, 13.0f, 0.0f)); + + SoundManip(1.5f, 1.0f, 0.5f); + m_phase = ALAP_OPEN3; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ALAP_OPEN3 ) + { + if ( m_progress < 1.0f ) + { + angle = (1.0f-m_progress)*PI/2.0f; + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, 0.0f); + + goal = m_object->RetPosition(0); + goal.y += 3.0f; + pos = goal; + pos.x -= 4.0f; + pos.y += 4.0f; + for ( i=0 ; i<3 ; i++ ) + { + m_partiRank[i] = m_particule->CreateRay(pos, goal, + PARTIRAY2, + FPOINT(2.9f, 2.9f), + LABO_DELAY); + } + + m_soundChannel = m_sound->Play(SOUND_LABO, m_object->RetPosition(0), 0.0f, 0.25f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.00f, 8.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 8.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 2.0f, SOPER_STOP); + + pos = m_object->RetPosition(0); + pos.y += 4.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 4.0f; + dim.y = dim.x; + m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE2, LABO_DELAY, 0.0f, 0.0f); + + m_phase = ALAP_ANALYSE; + m_progress = 0.0f; + m_speed = 1.0f/LABO_DELAY; + } + } + + if ( m_phase == ALAP_ANALYSE ) + { + if ( m_progress < 1.0f ) + { + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f-m_progress); + } + + angle = m_object->RetAngleY(2); + if ( m_progress < 0.5f ) + { + angle -= event.rTime*m_progress*20.0f; + } + else + { + angle -= event.rTime*(20.0f-m_progress*20.0f); + } + m_object->SetAngleY(2, angle); // rotates the analyzer + + angle += m_object->RetAngleY(0); + for ( i=0 ; i<3 ; i++ ) + { + rot = RotatePoint(-angle, -4.0f); + pos = m_object->RetPosition(0); + pos.x += rot.x; + pos.z += rot.y; + pos.y += 3.0f+4.0f;; + m_particule->SetPosition(m_partiRank[i], pos); // adjusts ray + + angle += PI*2.0f/3.0f; + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + if ( m_progress > 0.25f && + m_progress < 0.80f ) + { + pos = m_object->RetPosition(0); + pos.y += 3.0f; + pos.x += (Rand()-0.5f)*2.0f; + pos.z += (Rand()-0.5f)*2.0f; + speed.y = Rand()*5.0f+5.0f; + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + dim.x = Rand()*0.4f*m_progress+1.0f; + dim.y = dim.x; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, + 2.0f+2.0f*m_progress, 10.0f, 1.5f, 1.4f); + } + } + } + else + { + SetResearch(m_research); // research done + + power = m_object->RetPower(); + if ( power != 0 ) + { + m_object->SetPower(0); + power->DeleteObject(); // destroys the ball + delete power; + } + + m_displayText->DisplayError(INFO_LABO, m_object); + + SoundManip(1.5f, 1.0f, 0.5f); + m_phase = ALAP_CLOSE1; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ALAP_CLOSE1 ) + { + if ( m_progress < 1.0f ) + { + angle = m_progress*PI/2.0f; + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, PI/2.0f); + + SoundManip(1.5f, 1.0f, 0.7f); + m_phase = ALAP_CLOSE2; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ALAP_CLOSE2 ) + { + if ( m_progress < 1.0f ) + { + pos.x = -9.0f; + pos.y = 3.0f+(1.0f-m_progress)*10.0f;; + pos.z = 0.0f; + m_object->SetPosition(1, pos); + } + else + { + m_object->SetPosition(1, D3DVECTOR(-9.0f, 3.0f, 0.0f)); + + SoundManip(1.0f, 1.0f, 1.0f); + m_phase = ALAP_CLOSE3; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ALAP_CLOSE3 ) + { + if ( m_progress < 1.0f ) + { + angle = 45.0f+(35.0f*m_progress); + m_object->SetAngleZ(3, angle*PI/180.0f); + m_object->SetAngleZ(4, angle*PI/180.0f); + m_object->SetAngleZ(5, angle*PI/180.0f); + } + else + { + m_object->SetAngleZ(3, 80.0f*PI/180.0f); + m_object->SetAngleZ(4, 80.0f*PI/180.0f); + m_object->SetAngleZ(5, 80.0f*PI/180.0f); + + SetBusy(FALSE); + UpdateInterface(); + + m_phase = ALAP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoLabo::RetError() +{ + CObject* pObj; + ObjectType type; + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + pObj = m_object->RetPower(); + if ( pObj == 0 ) return ERR_LABO_NULL; + type = pObj->RetType(); + if ( type != OBJECT_BULLET ) return ERR_LABO_BAD; + + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoLabo::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW); + + pos.x = ox+sx*8.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 111, EVENT_OBJECT_TYPE); + + UpdateInterface(); + + return TRUE; +} + +// Updates the status of all interface buttons. + +void CAutoLabo::UpdateInterface() +{ + CWindow* pw; + + if ( !m_object->RetSelect() ) return; + + CAuto::UpdateInterface(); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + DeadInterface(pw, EVENT_OBJECT_RiPAW, g_researchEnable&RESEARCH_iPAW); + DeadInterface(pw, EVENT_OBJECT_RiGUN, g_researchEnable&RESEARCH_iGUN); + + OkayButton(pw, EVENT_OBJECT_RiPAW); + OkayButton(pw, EVENT_OBJECT_RiGUN); + + VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy); +} + +// Indicates the research conducted for a button. + +void CAutoLabo::OkayButton(CWindow *pw, EventMsg event) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_OKAY, TestResearch(event)); +} + + +// Test whether a search has already been done. + +BOOL CAutoLabo::TestResearch(EventMsg event) +{ + if ( event == EVENT_OBJECT_RiPAW ) return (g_researchDone & RESEARCH_iPAW); + if ( event == EVENT_OBJECT_RiGUN ) return (g_researchDone & RESEARCH_iGUN); + + return FALSE; +} + +// Indicates a search as made. + +void CAutoLabo::SetResearch(EventMsg event) +{ + Event newEvent; + + if ( event == EVENT_OBJECT_RiPAW ) g_researchDone |= RESEARCH_iPAW; + if ( event == EVENT_OBJECT_RiGUN ) g_researchDone |= RESEARCH_iGUN; + + m_main->WriteFreeParam(); + + m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE); + m_event->AddEvent(newEvent); + UpdateInterface(); +} + +// Plays the sound of the manipulator arm. + +void CAutoLabo::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, TRUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + + +// Saves all parameters of the controller. + +BOOL CAutoLabo::Write(char *line) +{ + D3DVECTOR pos; + char name[100]; + + if ( m_phase == ALAP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + sprintf(name, " aResearch=%d", m_research); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoLabo::Read(char *line) +{ + D3DVECTOR pos; + + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoLaboPhase)OpInt(line, "aPhase", ALAP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + m_research = (EventMsg)OpInt(line, "aResearch", 0); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autolabo.h b/src/object/auto/autolabo.h new file mode 100644 index 0000000..997bc55 --- /dev/null +++ b/src/object/auto/autolabo.h @@ -0,0 +1,87 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autolabo.h + +#ifndef _AUTOLABO_H_ +#define _AUTOLABO_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoLaboPhase +{ + ALAP_WAIT = 1, + ALAP_OPEN1 = 2, + ALAP_OPEN2 = 3, + ALAP_OPEN3 = 4, + ALAP_ANALYSE = 5, + ALAP_CLOSE1 = 6, + ALAP_CLOSE2 = 7, + ALAP_CLOSE3 = 8, +}; + + + +class CAutoLabo : public CAuto +{ +public: + CAutoLabo(CInstanceManager* iMan, CObject* object); + ~CAutoLabo(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(); + void OkayButton(CWindow *pw, EventMsg event); + BOOL TestResearch(EventMsg event); + void SetResearch(EventMsg event); + void SoundManip(float time, float amplitude, float frequency); + +protected: + AutoLaboPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + EventMsg m_research; + int m_partiRank[3]; + int m_partiSphere; + int m_soundChannel; +}; + + +#endif //_AUTOLABO_H_ diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp new file mode 100644 index 0000000..d1107ed --- /dev/null +++ b/src/object/auto/automush.cpp @@ -0,0 +1,362 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "cmdtoken.h" +#include "sound.h" +#include "auto.h" +#include "automush.h" + + + + +// Object's constructor. + +CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoMush::~CAutoMush() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoMush::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoMush::Init() +{ + m_phase = AMP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/4.0f; + + m_time = 0.0f; + m_lastParticule = 0.0f; +} + + +// Management of an event. + +BOOL CAutoMush::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed, dir; + FPOINT dim; + float factor, zoom, size, angle; + int i, channel; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + + factor = 0.0f; + size = 1.0f; + + if ( m_phase == AMP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + if ( !SearchTarget() ) + { + m_phase = AMP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/(2.0f+Rand()*2.0f); + } + else + { + m_phase = AMP_SNIF; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + } + + if ( m_phase == AMP_SNIF ) + { + if ( m_progress < 1.0f ) + { + factor = m_progress; + } + else + { + m_phase = AMP_ZOOM; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == AMP_ZOOM ) + { + if ( m_progress < 1.0f ) + { + factor = 1.0f; + size = 1.0f+m_progress*0.3f; + } + else + { + m_sound->Play(SOUND_MUSHROOM, m_object->RetPosition(0)); + + m_phase = AMP_FIRE; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == AMP_FIRE ) + { + if ( m_progress < 1.0f ) + { + factor = 1.0f-m_progress; + size = 1.0f+(1.0f-m_progress)*0.3f; + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<10 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.y += 5.0f; + speed.x = (Rand()-0.5f)*200.0f; + speed.z = (Rand()-0.5f)*200.0f; + speed.y = -(20.0f+Rand()*20.0f); + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + } + } + else + { + m_phase = AMP_SMOKE; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == AMP_SMOKE ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y += 5.0f; + speed.x = (Rand()-0.5f)*4.0f; + speed.z = (Rand()-0.5f)*4.0f; + speed.y = -(0.5f+Rand()*0.5f); + dim.x = Rand()*2.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f); + } + } + else + { + m_phase = AMP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/(2.0f+Rand()*2.0f); + } + } + + if ( factor != 0.0f || size != 1.0f ) + { + dir.x = sinf(m_time*PI*4.0f); + dir.z = cosf(m_time*PI*4.0f); + + angle = sinf(m_time*10.0f)*factor*0.04f; + m_object->SetAngleX(0, angle*dir.z); + m_object->SetAngleZ(0, angle*dir.x); + + zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f; + m_object->SetZoomX(0, zoom*size); + zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f; + m_object->SetZoomY(0, zoom*size); + zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f; + m_object->SetZoomZ(0, zoom*size); + } + else + { + m_object->SetAngleX(0, 0.0f); + m_object->SetAngleZ(0, 0.0f); + m_object->SetZoom(0, D3DVECTOR(1.0f, 1.0f, 1.0f)); + } + + return TRUE; +} + + +// Seeking a nearby target. + +BOOL CAutoMush::SearchTarget() +{ + CObject* pObj; + D3DVECTOR iPos, oPos; + ObjectType type; + float dist; + int i; + + iPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetLock() ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_DERRICK && + type != OBJECT_STATION && + type != OBJECT_FACTORY && + type != OBJECT_REPAIR && + type != OBJECT_DESTROYER&& + type != OBJECT_CONVERT && + type != OBJECT_TOWER && + type != OBJECT_RESEARCH && + type != OBJECT_RADAR && + type != OBJECT_INFO && + type != OBJECT_ENERGY && + type != OBJECT_LABO && + type != OBJECT_NUCLEAR && + type != OBJECT_PARA && + type != OBJECT_HUMAN ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, iPos); + if ( dist < 50.0f ) return TRUE; + } + + return FALSE; +} + + +// Returns an error due the state of the automation. + +Error CAutoMush::RetError() +{ + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoMush::Write(char *line) +{ + D3DVECTOR pos; + char name[100]; + + if ( m_phase == AMP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoMush::Read(char *line) +{ + D3DVECTOR pos; + + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoMushPhase)OpInt(line, "aPhase", AMP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/automush.h b/src/object/auto/automush.h new file mode 100644 index 0000000..81314ee --- /dev/null +++ b/src/object/auto/automush.h @@ -0,0 +1,73 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// automush.h + +#ifndef _AUTOMUSH_H_ +#define _AUTOMUSH_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoMushPhase +{ + AMP_WAIT = 1, + AMP_SNIF = 2, + AMP_ZOOM = 3, + AMP_FIRE = 4, + AMP_SMOKE = 5, +}; + + + +class CAutoMush : public CAuto +{ +public: + CAutoMush(CInstanceManager* iMan, CObject* object); + ~CAutoMush(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + BOOL SearchTarget(); + +protected: + AutoMushPhase m_phase; + float m_progress; + float m_speed; + float m_lastParticule; +}; + + +#endif //_AUTOMUSH_H_ diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp new file mode 100644 index 0000000..a86e7b8 --- /dev/null +++ b/src/object/auto/autonest.cpp @@ -0,0 +1,291 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autonest.h" + + + + +// Object's constructor. + +CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoNest::~CAutoNest() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoNest::DeleteObject(BOOL bAll) +{ + CObject* fret; + + if ( !bAll ) + { + fret = SearchFret(); + if ( fret != 0 ) + { + fret->DeleteObject(); + delete fret; + } + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoNest::Init() +{ + D3DVECTOR pos; + + m_phase = ANP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/4.0f; + + m_time = 0.0f; + m_lastParticule = 0.0f; + + pos = m_object->RetPosition(0); + m_terrain->MoveOnFloor(pos); + m_fretPos = pos; +} + + +// Management of an event. + +BOOL CAutoNest::EventProcess(const Event &event) +{ + CObject* fret; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + + if ( m_phase == ANP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + if ( !SearchFree(m_fretPos) ) + { + m_phase = ANP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/4.0f; + } + else + { + CreateFret(m_fretPos, 0.0f, OBJECT_BULLET); + m_phase = ANP_BIRTH; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + } + + if ( m_phase == ANP_BIRTH ) + { + fret = SearchFret(); + + if ( m_progress < 1.0f ) + { + if ( fret != 0 ) + { + fret->SetZoom(0, m_progress); + } + } + else + { + if ( fret != 0 ) + { + fret->SetZoom(0, 1.0f); + fret->SetLock(FALSE); + } + + m_phase = ANP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/5.0f; + } + } + + return TRUE; +} + + +// Seeks if a site is free. + +BOOL CAutoNest::SearchFree(D3DVECTOR pos) +{ + CObject* pObj; + D3DVECTOR sPos; + ObjectType type; + float sRadius, distance; + int i, j; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_NEST ) continue; + + j = 0; + while ( pObj->GetCrashSphere(j++, sPos, sRadius) ) + { + distance = Length(sPos, pos); + distance -= sRadius; + if ( distance < 2.0f ) return FALSE; // location occupied + } + } + + return TRUE; // free location +} + +// Create a transportable object. + +void CAutoNest::CreateFret(D3DVECTOR pos, float angle, ObjectType type) +{ + CObject* fret; + + fret = new CObject(m_iMan); + if ( !fret->CreateResource(pos, angle, type) ) + { + delete fret; + return; + } + fret->SetLock(TRUE); // not usable + fret->SetZoom(0, 0.0f); +} + +// Looking for the ball during manufacture. + +CObject* CAutoNest::SearchFret() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetLock() ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_BULLET ) continue; + + oPos = pObj->RetPosition(0); + if ( oPos.x == m_fretPos.x && + oPos.z == m_fretPos.z ) + { + return pObj; + } + } + + return 0; +} + + +// Returns an error due the state of the automation. + +Error CAutoNest::RetError() +{ + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoNest::Write(char *line) +{ + D3DVECTOR pos; + char name[100]; + + if ( m_phase == ANP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoNest::Read(char *line) +{ + D3DVECTOR pos; + + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoNestPhase)OpInt(line, "aPhase", ANP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autonest.h b/src/object/auto/autonest.h new file mode 100644 index 0000000..0c6febc --- /dev/null +++ b/src/object/auto/autonest.h @@ -0,0 +1,73 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autonest.h + +#ifndef _AUTONEST_H_ +#define _AUTONEST_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoNestPhase +{ + ANP_WAIT = 1, + ANP_BIRTH = 2, // appearance of a ball +}; + + + +class CAutoNest : public CAuto +{ +public: + CAutoNest(CInstanceManager* iMan, CObject* object); + ~CAutoNest(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + BOOL SearchFree(D3DVECTOR pos); + void CreateFret(D3DVECTOR pos, float angle, ObjectType type); + CObject* SearchFret(); + +protected: + AutoNestPhase m_phase; + float m_progress; + float m_speed; + float m_lastParticule; + D3DVECTOR m_fretPos; +}; + + +#endif //_AUTONEST_H_ diff --git a/src/object/auto/autonuclear.cpp b/src/object/auto/autonuclear.cpp new file mode 100644 index 0000000..824bfca --- /dev/null +++ b/src/object/auto/autonuclear.cpp @@ -0,0 +1,504 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autonuclear.h" + + + +#define NUCLEAR_DELAY 30.0f // duration of the generation + + + + +// Object's constructor. + +CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_channelSound = -1; + Init(); +} + +// Object's destructor. + +CAutoNuclear::~CAutoNuclear() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoNuclear::DeleteObject(BOOL bAll) +{ + CObject* fret; + + if ( !bAll ) + { + fret = SearchUranium(); + if ( fret != 0 ) + { + fret->DeleteObject(); // destroys the metal + delete fret; + } + } + + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoNuclear::Init() +{ + D3DMATRIX* mat; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + mat = m_object->RetWorldMatrix(0); + m_pos = Transform(*mat, D3DVECTOR(22.0f, 4.0f, 0.0f)); + + m_phase = ANUP_WAIT; // waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoNuclear::EventProcess(const Event &event) +{ + CObject* fret; + D3DMATRIX* mat; + D3DVECTOR pos, goal, speed; + FPOINT dim, rot; + float angle; + int i, max; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + EventProgress(event.rTime); + + if ( m_phase == ANUP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + fret = SearchUranium(); // transform uranium? + if ( fret == 0 || SearchVehicle() ) + { + m_phase = ANUP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + else + { + fret->SetLock(TRUE); // usable uranium + + SetBusy(TRUE); + InitProgressTotal(1.5f+NUCLEAR_DELAY+1.5f); + UpdateInterface(); + + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f); + + m_phase = ANUP_CLOSE; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + } + + if ( m_phase == ANUP_CLOSE ) + { + if ( m_progress < 1.0f ) + { + angle = (1.0f-m_progress)*(135.0f*PI/180.0f); + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, 0.0f); + + mat = m_object->RetWorldMatrix(0); + max = (int)(10.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTICRASH); + } + + m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 1.0f); + + m_channelSound = m_sound->Play(SOUND_NUCLEAR, m_object->RetPosition(0), 1.0f, 0.1f, TRUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, NUCLEAR_DELAY-1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP); + + m_phase = ANUP_GENERATE; + m_progress = 0.0f; + m_speed = 1.0f/NUCLEAR_DELAY; + } + } + + if ( m_phase == ANUP_GENERATE ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.y += 30.0f; + pos.x += (Rand()-0.5f)*6.0f; + pos.z += (Rand()-0.5f)*6.0f; + speed.y = Rand()*15.0f+15.0f; + speed.x = 0.0f; + speed.z = 0.0f; + dim.x = Rand()*8.0f+8.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH); + + pos = m_pos; + speed.x = (Rand()-0.5f)*20.0f; + speed.y = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f); + } + } + else + { + fret = SearchUranium(); + if ( fret != 0 ) + { + fret->DeleteObject(); // destroyed uranium + delete fret; + m_object->SetPower(0); + } + + CreatePower(); // creates the atomic cell + + max = (int)(20.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateParticule(pos, speed, dim, PARTIBLUE, Rand()*5.0f+5.0f, 0.0f, 0.0f); + } + + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f); + + m_phase = ANUP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ANUP_OPEN ) + { + if ( m_progress < 1.0f ) + { + angle = m_progress*(135.0f*PI/180.0f); + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, 135.0f*PI/180.0f); + + SetBusy(FALSE); + UpdateInterface(); + + m_displayText->DisplayError(INFO_NUCLEAR, m_object); + + m_phase = ANUP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoNuclear::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 110, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Seeking the uranium. + +CObject* CAutoNuclear::SearchUranium() +{ + CObject* pObj; + + pObj = m_object->RetPower(); + if ( pObj == 0 ) return 0; + if ( pObj->RetType() == OBJECT_URANIUM ) return pObj; + return 0; +} + +// Seeks if a vehicle is too close. + +BOOL CAutoNuclear::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float oRadius, dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, m_pos)-oRadius; + + if ( dist < 10.0f ) return TRUE; + } + + return FALSE; +} + +// Creates an object stack. + +void CAutoNuclear::CreatePower() +{ + CObject* power; + D3DVECTOR pos; + float angle; + + pos = m_object->RetPosition(0); + angle = m_object->RetAngleY(0); + + power = new CObject(m_iMan); + if ( !power->CreateResource(pos, angle, OBJECT_ATOMIC) ) + { + delete power; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return; + } + + power->SetTruck(m_object); + power->SetPosition(0, D3DVECTOR(22.0f, 3.0f, 0.0f)); + m_object->SetPower(power); +} + + +// Returns an error due the state of the automation. + +Error CAutoNuclear::RetError() +{ + CObject* pObj; + ObjectType type; +//? TerrainRes res; + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + +//? res = m_terrain->RetResource(m_object->RetPosition(0)); +//? if ( res != TR_POWER ) return ERR_NUCLEAR_NULL; + +//? if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_NUCLEAR_LOW; + + pObj = m_object->RetPower(); + if ( pObj == 0 ) return ERR_NUCLEAR_EMPTY; + if ( pObj->RetLock() ) return ERR_OK; + type = pObj->RetType(); + if ( type == OBJECT_ATOMIC ) return ERR_OK; + if ( type != OBJECT_URANIUM ) return ERR_NUCLEAR_BAD; + + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoNuclear::Write(char *line) +{ + char name[100]; + + if ( m_phase == ANUP_STOP || + m_phase == ANUP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoNuclear::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoNuclearPhase)OpInt(line, "aPhase", ANUP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autonuclear.h b/src/object/auto/autonuclear.h new file mode 100644 index 0000000..e62282a --- /dev/null +++ b/src/object/auto/autonuclear.h @@ -0,0 +1,80 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autonuclear.h + +#ifndef _AUTONUCLEAR_H_ +#define _AUTONUCLEAR_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoNuclearPhase +{ + ANUP_STOP = 1, + ANUP_WAIT = 2, + ANUP_CLOSE = 3, + ANUP_GENERATE = 4, + ANUP_OPEN = 5, +}; + + + +class CAutoNuclear : public CAuto +{ +public: + CAutoNuclear(CInstanceManager* iMan, CObject* object); + ~CAutoNuclear(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchUranium(); + BOOL SearchVehicle(); + void CreatePower(); + +protected: + AutoNuclearPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + D3DVECTOR m_pos; + int m_channelSound; +}; + + +#endif //_AUTONUCLEAR_H_ diff --git a/src/object/auto/autopara.cpp b/src/object/auto/autopara.cpp new file mode 100644 index 0000000..cb42e6d --- /dev/null +++ b/src/object/auto/autopara.cpp @@ -0,0 +1,347 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autopara.h" + + + + +// Object's constructor. + +CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + m_channelSound = -1; + Init(); +} + +// Object's destructor. + +CAutoPara::~CAutoPara() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoPara::DeleteObject(BOOL bAll) +{ + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoPara::Init() +{ + D3DMATRIX* mat; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + mat = m_object->RetWorldMatrix(0); + m_pos = Transform(*mat, D3DVECTOR(22.0f, 4.0f, 0.0f)); + + m_phase = APAP_WAIT; // waiting ... + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + CAuto::Init(); +} + + +// Reception of lightning. + +void CAutoPara::StartBlitz() +{ + m_phase = APAP_BLITZ; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; +} + + +// Management of an event. + +BOOL CAutoPara::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed; + FPOINT dim; + int i; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + EventProgress(event.rTime); + + if ( m_phase == APAP_BLITZ ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<10 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*m_progress*40.0f; + pos.z += (Rand()-0.5f)*m_progress*40.0f; + pos.y += 50.0f-m_progress*50.0f; + speed.x = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + speed.y = 5.0f+Rand()*5.0f; + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 20.0f, 0.5f); + } + } + } + else + { + m_phase = APAP_CHARGE; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_phase == APAP_CHARGE ) + { + if ( m_progress < 1.0f ) + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<2 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.y += 16.0f; + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = -Rand()*30.0f; + dim.x = 1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f); + } + } + + ChargeObject(event.rTime); + } + else + { + m_phase = APAP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoPara::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 113, EVENT_OBJECT_TYPE); + + pos.x = ox+sx*10.2f; + pos.y = oy+sy*0.5f; + ddim.x = 33.0f/640.0f; + ddim.y = 33.0f/480.0f; + pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT); + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoPara::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + return ERR_OK; +} + + +// Load all objects under the lightning rod. + +void CAutoPara::ChargeObject(float rTime) +{ + CObject* pObj; + CObject* power; + D3DVECTOR sPos, oPos; + float dist, energy; + int i; + + sPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, sPos); + if ( dist > 20.0f ) continue; + + if ( pObj->RetTruck() == 0 && pObj->RetType() == OBJECT_POWER ) + { + energy = pObj->RetEnergy(); + energy += rTime/2.0f; + if ( energy > 1.0f ) energy = 1.0f; + pObj->SetEnergy(energy); + } + + power = pObj->RetPower(); + if ( power != 0 && power->RetType() == OBJECT_POWER ) + { + energy = power->RetEnergy(); + energy += rTime/2.0f; + if ( energy > 1.0f ) energy = 1.0f; + power->SetEnergy(energy); + } + + power = pObj->RetFret(); + if ( power != 0 && power->RetType() == OBJECT_POWER ) + { + energy = power->RetEnergy(); + energy += rTime/2.0f; + if ( energy > 1.0f ) energy = 1.0f; + power->SetEnergy(energy); + } + } +} + + +// Saves all parameters of the controller. + +BOOL CAutoPara::Write(char *line) +{ + char name[100]; + + if ( m_phase == APAP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoPara::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoParaPhase)OpInt(line, "aPhase", APAP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autopara.h b/src/object/auto/autopara.h new file mode 100644 index 0000000..9a7c0c4 --- /dev/null +++ b/src/object/auto/autopara.h @@ -0,0 +1,77 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autopara.h + +#ifndef _AUTOPARA_H_ +#define _AUTOPARA_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoParaPhase +{ + APAP_WAIT = 1, + APAP_BLITZ = 2, + APAP_CHARGE = 3, +}; + + + +class CAutoPara : public CAuto +{ +public: + CAutoPara(CInstanceManager* iMan, CObject* object); + ~CAutoPara(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + void StartBlitz(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void ChargeObject(float rTime); + +protected: + AutoParaPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + D3DVECTOR m_pos; + int m_channelSound; +}; + + +#endif //_AUTOPARA_H_ diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp new file mode 100644 index 0000000..c02348d --- /dev/null +++ b/src/object/auto/autoportico.cpp @@ -0,0 +1,446 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "displaytext.h" +#include "robotmain.h" +#include "sound.h" +#include "auto.h" +#include "autoportico.h" + + + +#define PARAM_DEPOSE 2 // run=2 -> deposits the spaceship + +#define PORTICO_POSa 75.0f +#define PORTICO_POSb 65.0f +#define PORTICO_ANGLE1a ( 25.0f*PI/180.0f) +#define PORTICO_ANGLE1b ( 70.0f*PI/180.0f) +#define PORTICO_ANGLE2a (-37.5f*PI/180.0f) +#define PORTICO_ANGLE2b (-62.5f*PI/180.0f) +#define PORTICO_ANGLE3a (-77.5f*PI/180.0f) +#define PORTICO_ANGLE3b (-30.0f*PI/180.0f) + +#define PORTICO_TIME_MOVE 16.0f +#define PORTICO_TIME_DOWN 4.0f +#define PORTICO_TIME_OPEN 12.0f + + + + +// Si progress=0, return a. +// Si progress=1, return b. + +float Progress(float a, float b, float progress) +{ + return a+(b-a)*progress; +} + + + +// Object's constructor. + +CAutoPortico::CAutoPortico(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = APOP_WAIT; + m_soundChannel = -1; +} + +// Object's destructor. + +CAutoPortico::~CAutoPortico() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoPortico::DeleteObject(BOOL bAll) +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoPortico::Init() +{ + m_time = 0.0f; + m_lastParticule = 0.0f; + m_posTrack = 0.0f; + + m_phase = APOP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + m_cameraProgress = 0.0f; + m_cameraSpeed = 1.0f/(PORTICO_TIME_MOVE-2.0f); +} + + +// Starts the object. + +void CAutoPortico::Start(int param) +{ + D3DVECTOR pos; + + pos = m_object->RetPosition(0); + m_finalPos = pos; + pos.z += PORTICO_TIME_MOVE*5.0f; // back to start + m_object->SetPosition(0, pos); + m_finalPos.z += PORTICO_TIME_OPEN*5.3f; + + m_object->SetPosition(1, D3DVECTOR(0.0f, PORTICO_POSa, 0.0f)); + m_object->SetAngleY(2, PORTICO_ANGLE1a); + m_object->SetAngleY(3, PORTICO_ANGLE2a); + m_object->SetAngleY(4, PORTICO_ANGLE3a); + m_object->SetAngleY(5, -PORTICO_ANGLE1a); + m_object->SetAngleY(6, -PORTICO_ANGLE2a); + m_object->SetAngleY(7, -PORTICO_ANGLE3a); + + m_phase = APOP_START; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + m_param = param; +} + + +// Management of an event. + +BOOL CAutoPortico::EventProcess(const Event &event) +{ + CObject* pObj; + D3DVECTOR pos; + float angle; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + if ( m_phase == APOP_START ) + { + if ( m_param == PARAM_DEPOSE ) // deposits the ship? + { + m_startPos = m_object->RetPosition(0); + + m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_MOVE-0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP); + + m_phase = APOP_MOVE; + m_progress = 0.0f; + m_speed = 1.0f/PORTICO_TIME_MOVE; + + m_main->SetMovieLock(TRUE); // blocks everything until the end of the landing + + m_camera->SetType(CAMERA_SCRIPT); + + pos = m_startPos; + pos.x += -100.0f; + pos.y += 9.0f; + pos.z += -200.0f; + m_camera->SetScriptEye(pos); + + pos = m_object->RetPosition(0); + pos.x += 0.0f; + pos.y += 10.0f; + pos.z += -40.0f; + m_camera->SetScriptLookat(pos); + + m_camera->FixCamera(); + } + } + + angle = -m_time*1.0f; + m_object->SetAngleY(8, angle); // rotates the radar right + angle = sinf(m_time*4.0f)*0.3f; + m_object->SetAngleX(9, angle); + + angle = -m_time*1.0f+PI/2.3f; + m_object->SetAngleY(10, angle); // turns the left side radar + angle = sinf(m_time*4.0f)*0.3f; + m_object->SetAngleX(11, angle); + + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_phase == APOP_WAIT ) return TRUE; + + m_progress += event.rTime*m_speed; + m_cameraProgress += event.rTime*m_cameraSpeed; + + if ( m_phase == APOP_MOVE ) + { + if ( m_progress < 1.0f ) + { + pos = m_object->RetPosition(0); + pos.z -= event.rTime*5.0f; // advance + m_object->SetPosition(0, pos); + + m_posTrack += event.rTime*0.5f; + UpdateTrackMapping(m_posTrack, m_posTrack); + } + else + { + m_phase = APOP_WAIT1; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == APOP_WAIT1 ) + { + if ( m_progress >= 1.0f ) + { + m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.6f, PORTICO_TIME_DOWN-1.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP); + + m_phase = APOP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/PORTICO_TIME_DOWN; + } + } + + if ( m_phase == APOP_DOWN ) + { + if ( m_progress < 1.0f ) + { + pos.x = 0.0f; + pos.y = Progress(PORTICO_POSa, PORTICO_POSb, m_progress); + pos.z = 0.0f; + m_object->SetPosition(1, pos); + } + else + { + pos.x = 0.0f; + pos.y = PORTICO_POSb; + pos.z = 0.0f; + m_object->SetPosition(1, pos); + + m_phase = APOP_WAIT2; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == APOP_WAIT2 ) + { + if ( m_progress >= 1.0f ) + { + m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, 0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, PORTICO_TIME_OPEN/2.0f-0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP); + + m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_OPEN-0.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP); + + m_phase = APOP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/PORTICO_TIME_OPEN; + } + } + + if ( m_phase == APOP_OPEN ) + { + if ( m_progress < 1.0f ) + { + pos = m_object->RetPosition(0); + pos.z += event.rTime*5.3f; // back + m_object->SetPosition(0, pos); + + m_posTrack -= event.rTime*1.0f; + UpdateTrackMapping(m_posTrack, m_posTrack); + + if ( m_progress < 0.5f ) + { + angle = Progress(PORTICO_ANGLE1a, PORTICO_ANGLE1b, m_progress/0.5f); + m_object->SetAngleY(2, angle); + m_object->SetAngleY(5, -angle); + angle = Progress(PORTICO_ANGLE2a, PORTICO_ANGLE2b, m_progress/0.5f); + m_object->SetAngleY(3, angle); + m_object->SetAngleY(6, -angle); + angle = Progress(PORTICO_ANGLE3a, PORTICO_ANGLE3b, m_progress/0.5f); + m_object->SetAngleY(4, angle); + m_object->SetAngleY(7, -angle); + } + else + { + m_object->SetAngleY(2, PORTICO_ANGLE1b); + m_object->SetAngleY(3, PORTICO_ANGLE2b); + m_object->SetAngleY(4, PORTICO_ANGLE3b); + m_object->SetAngleY(5, -PORTICO_ANGLE1b); + m_object->SetAngleY(6, -PORTICO_ANGLE2b); + m_object->SetAngleY(7, -PORTICO_ANGLE3b); + } + } + else + { + m_main->SetMovieLock(FALSE); // you can play! + + pObj = m_main->SearchHuman(); + m_main->SelectObject(pObj); + m_camera->SetObject(pObj); + m_camera->SetType(CAMERA_BACK); + + m_phase = APOP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + } + } + + if ( m_soundChannel != -1 ) + { +//? m_sound->Position(m_soundChannel, m_object->RetPosition(0)); + pos = m_engine->RetEyePt(); + m_sound->Position(m_soundChannel, pos); + } + + if ( m_cameraProgress < 1.0f ) + { + if ( m_cameraProgress < 0.5f ) + { + } + else + { + pos = m_startPos; + pos.x += -100.0f-(m_cameraProgress-0.5f)*1.0f*120.0f; + pos.y += 9.0f; + pos.z += -200.0f+(m_cameraProgress-0.5f)*1.0f*210.0f; + m_camera->SetScriptEye(pos); + } + + pos = m_object->RetPosition(0); + pos.x += 0.0f; + pos.y += 10.0f; + pos.z += -40.0f; + m_camera->SetScriptLookat(pos); + } + + return TRUE; +} + +// Stops the controller. + +BOOL CAutoPortico::Abort() +{ + CObject* pObj; + + m_object->SetPosition(0, m_finalPos); + m_object->SetPosition(1, D3DVECTOR(0.0f, PORTICO_POSb, 0.0f)); + m_object->SetAngleY(2, PORTICO_ANGLE1b); + m_object->SetAngleY(3, PORTICO_ANGLE2b); + m_object->SetAngleY(4, PORTICO_ANGLE3b); + m_object->SetAngleY(5, -PORTICO_ANGLE1b); + m_object->SetAngleY(6, -PORTICO_ANGLE2b); + m_object->SetAngleY(7, -PORTICO_ANGLE3b); + + m_main->SetMovieLock(FALSE); // you can play! + + pObj = m_main->SearchHuman(); + m_main->SelectObject(pObj); + m_camera->SetObject(pObj); + m_camera->SetType(CAMERA_BACK); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_phase = APOP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/2.0f; + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoPortico::RetError() +{ + return ERR_OK; +} + + +// Updates the mapping of the texture of the caterpillars. + +void CAutoPortico::UpdateTrackMapping(float left, float right) +{ + D3DMATERIAL7 mat; + float limit[2]; + int rank; + + ZeroMemory( &mat, sizeof(D3DMATERIAL7) ); + mat.diffuse.r = 1.0f; + mat.diffuse.g = 1.0f; + mat.diffuse.b = 1.0f; // blank + mat.ambient.r = 0.5f; + mat.ambient.g = 0.5f; + mat.ambient.b = 0.5f; + + rank = m_object->RetObjectRank(0); + + limit[0] = 0.0f; + limit[1] = 1000000.0f; + + m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART1, "lemt.tga", "", + limit[0], limit[1], D3DMAPPINGX, + right, 8.0f, 8.0f, 192.0f, 256.0f); + + m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART2, "lemt.tga", "", + limit[0], limit[1], D3DMAPPINGX, + left, 8.0f, 8.0f, 192.0f, 256.0f); +} + diff --git a/src/object/auto/autoportico.h b/src/object/auto/autoportico.h new file mode 100644 index 0000000..7ed2e70 --- /dev/null +++ b/src/object/auto/autoportico.h @@ -0,0 +1,81 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoportico.h + +#ifndef _AUTOPORTICO_H_ +#define _AUTOPORTICO_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoPorticoPhase +{ + APOP_WAIT = 1, // waits + APOP_START = 2, // start of the action + APOP_MOVE = 3, // advance + APOP_WAIT1 = 4, // waits + APOP_DOWN = 5, // down + APOP_WAIT2 = 6, // waits + APOP_OPEN = 7, // opens +}; + + + +class CAutoPortico : public CAuto +{ +public: + CAutoPortico(CInstanceManager* iMan, CObject* object); + ~CAutoPortico(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + void Start(int param); + BOOL EventProcess(const Event &event); + BOOL Abort(); + Error RetError(); + +protected: + void UpdateTrackMapping(float left, float right); + +protected: + AutoPorticoPhase m_phase; + float m_progress; + float m_speed; + float m_cameraProgress; + float m_cameraSpeed; + float m_lastParticule; + D3DVECTOR m_finalPos; + D3DVECTOR m_startPos; + float m_posTrack; + int m_param; + int m_soundChannel; +}; + + +#endif //_AUTOPORTICO_H_ diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp new file mode 100644 index 0000000..2353149 --- /dev/null +++ b/src/object/auto/autoradar.cpp @@ -0,0 +1,326 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "gauge.h" +#include "sound.h" +#include "auto.h" +#include "autoradar.h" + + + + +// Object's constructor. + +CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = ARAP_WAIT; + m_totalDetect = 0; +} + +// Object's destructor. + +CAutoRadar::~CAutoRadar() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoRadar::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoRadar::Init() +{ + m_phase = ARAP_SEARCH; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + + m_aTime = 0.0f; + m_time = 0.0f; + m_timeVirus = 0.0f; +} + + +// Management of an event. + +BOOL CAutoRadar::EventProcess(const Event &event) +{ + D3DVECTOR pos, ePos; + float speed, angle, prog, freq, ampl; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_phase == ARAP_WAIT ) return TRUE; + + m_progress += event.rTime*m_speed; + m_aTime += event.rTime; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + angle = m_object->RetAngleY(1); + angle += (Rand()-0.2f)*0.5f; + m_object->SetAngleY(1, angle); + + angle = m_object->RetAngleY(2); + angle += (Rand()-0.8f)*1.0f; + m_object->SetAngleY(2, angle); + + m_object->SetAngleX(3, (Rand()-0.5f)*0.3f); + + m_totalDetect = (int)(Rand()*10.0f); + UpdateInterface(); + } + return TRUE; + } + + if ( m_phase == ARAP_SEARCH ) + { + if ( m_progress < 1.0f ) + { + speed = Min(10.0f, m_progress*50.0f); + angle = m_object->RetAngleY(1); + angle += event.rTime*speed; + m_object->SetAngleY(1, angle); + } + else + { + if ( !SearchEnemy(ePos) ) + { + m_phase = ARAP_SEARCH; + m_progress = 10.0f/50.0f; // full speed immediately + m_speed = 1.0f/3.0f; + } + else + { + pos = m_object->RetPosition(0); + m_start = m_object->RetAngleY(1); + m_angle = m_start-NormAngle(m_start)+PI*2.0f; + m_angle += RotateAngle(pos.x-ePos.x, ePos.z-pos.z); + m_angle += PI-m_object->RetAngleY(0); + + m_phase = ARAP_SHOW; + m_progress = 0.0f; + m_speed = 1.0f/(Abs(m_angle-m_start)/10.0f); + } + } + } + + if ( m_phase == ARAP_SHOW ) + { + if ( m_progress < 1.0f ) + { + angle = m_start + (m_angle-m_start)*m_progress; + m_object->SetAngleY(1, angle); + } + else + { + m_sound->Play(SOUND_RADAR, m_object->RetPosition(0)); + + m_phase = ARAP_SINUS; + m_progress = 0.0f; + m_speed = 1.0f/4.0f; + m_time = 0.0f; + } + } + + if ( m_phase == ARAP_SINUS ) + { + if ( m_progress < 1.0f ) + { + prog = Min(1.0f, m_progress*2.0f); + freq = 16.0f*(prog+1.0f); + ampl = 0.2f-prog*0.2f; + angle = m_angle + sinf(m_time*freq)*ampl; + m_object->SetAngleY(1, angle); + } + else + { + m_phase = ARAP_SEARCH; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + + angle = -m_aTime*2.0f; + m_object->SetAngleY(2, angle); + + angle = sinf(m_aTime*4.0f)*0.3f; + m_object->SetAngleX(3, angle); + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoRadar::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoRadar::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.6f; + dim.x = 160.0f/640.0f; + dim.y = 26.0f/480.0f; + pw->CreateGauge(pos, dim, 1, EVENT_OBJECT_GRADAR); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 105, EVENT_OBJECT_TYPE); + + UpdateInterface(); + return TRUE; +} + +// Updates the status of all interface buttons. + +void CAutoRadar::UpdateInterface() +{ + CWindow* pw; + CGauge* pg; + float level; + + if ( !m_object->RetSelect() ) return; + + CAuto::UpdateInterface(); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRADAR); + if ( pg != 0 ) + { + level = (float)m_totalDetect*(1.0f/8.0f); + if ( level > 1.0f ) level = 1.0f; + pg->SetLevel(level); + } +} + + +// Seeking the position of an enemy. + +BOOL CAutoRadar::SearchEnemy(D3DVECTOR &pos) +{ + CObject* pObj; + CObject* pBest = 0; + D3DVECTOR iPos, oPos; + ObjectType oType; + float distance, min; + int i; + + iPos = m_object->RetPosition(0); + min = 1000000.0f; + m_totalDetect = 0; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + + oType = pObj->RetType(); + if ( oType != OBJECT_ANT && + oType != OBJECT_SPIDER && + oType != OBJECT_BEE && + oType != OBJECT_WORM && + oType != OBJECT_MOTHER ) continue; + + m_totalDetect ++; + + oPos = pObj->RetPosition(0); + distance = Length(oPos, iPos); + if ( distance < min ) + { + min = distance; + pBest = pObj; + } + } + + UpdateInterface(); + + if ( pBest == 0 ) return FALSE; + pos = pBest->RetPosition(0); + return TRUE; +} + + diff --git a/src/object/auto/autoradar.h b/src/object/auto/autoradar.h new file mode 100644 index 0000000..298d011 --- /dev/null +++ b/src/object/auto/autoradar.h @@ -0,0 +1,76 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoradar.h + +#ifndef _AUTORADAR_H_ +#define _AUTORADAR_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoRadarPhase +{ + ARAP_WAIT = 1, // waiting + ARAP_SEARCH = 2, // seeking + ARAP_SHOW = 3, // watching + ARAP_SINUS = 4, // oscillates +}; + + + +class CAutoRadar : public CAuto +{ +public: + CAutoRadar(CInstanceManager* iMan, CObject* object); + ~CAutoRadar(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + BOOL CreateInterface(BOOL bSelect); + Error RetError(); + +protected: + void UpdateInterface(); + BOOL SearchEnemy(D3DVECTOR &pos); + +protected: + AutoRadarPhase m_phase; + float m_progress; + float m_speed; + float m_aTime; + float m_timeVirus; + float m_lastParticule; + float m_angle; + float m_start; + int m_totalDetect; +}; + + +#endif //_AUTORADAR_H_ diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp new file mode 100644 index 0000000..6994842 --- /dev/null +++ b/src/object/auto/autorepair.cpp @@ -0,0 +1,362 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "sound.h" +#include "interface.h" +#include "button.h" +#include "window.h" +#include "robotmain.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autorepair.h" + + + + +// Object's constructor. + +CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); + m_phase = ARP_WAIT; // paused until the first Init () +} + +// Object's destructor. + +CAutoRepair::~CAutoRepair() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoRepair::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoRepair::Init() +{ + m_phase = ARP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoRepair::EventProcess(const Event &event) +{ + CObject* vehicule; + D3DVECTOR pos, speed; + FPOINT dim; + float angle, shield; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + if ( m_phase == ARP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + if ( SearchVehicle() == 0 ) + { + m_phase = ARP_WAIT; // still waiting ... + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + else + { + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f); + + m_phase = ARP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + } + + if ( m_phase == ARP_DOWN ) + { + if ( m_progress < 1.0f ) + { + angle = -m_progress*(PI/2.0f)+PI/2.0f; + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, 0.0f); + m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0)); + + m_phase = ARP_REPAIR; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ARP_REPAIR ) + { + vehicule = SearchVehicle(); + if ( m_progress < 1.0f || + (vehicule != 0 && vehicule->RetShield() < 1.0f) ) + { + if ( vehicule != 0 ) + { + shield = vehicule->RetShield(); + shield += event.rTime*0.2f; + if ( shield > 1.0f ) shield = 1.0f; + vehicule->SetShield(shield); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + pos.y += 1.0f; + speed.x = (Rand()-0.5f)*12.0f; + speed.z = (Rand()-0.5f)*12.0f; + speed.y = Rand()*15.0f; + dim.x = Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); + } + } + else + { + m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f); + + m_phase = ARP_UP; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + + if ( m_phase == ARP_UP ) + { + if ( m_progress < 1.0f ) + { + angle = -(1.0f-m_progress)*(PI/2.0f)+PI/2.0f; + m_object->SetAngleZ(1, angle); + } + else + { + m_object->SetAngleZ(1, PI/2.0f); + + m_phase = ARP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoRepair::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Seeking the vehicle on the station. + +CObject* CAutoRepair::SearchVehicle() +{ + CObject* pObj; + CPhysics* physics; + D3DVECTOR sPos, oPos; + ObjectType type; + float dist; + int i; + + sPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr ) continue; + + physics = pObj->RetPhysics(); + if ( physics != 0 && !physics->RetLand() ) continue; // in flight? + + oPos = pObj->RetPosition(0); + dist = Length(oPos, sPos); + if ( dist <= 5.0f ) return pObj; + } + + return 0; +} + + +// Returns an error due the state of the automation. + +Error CAutoRepair::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoRepair::Write(char *line) +{ + char name[100]; + + if ( m_phase == ARP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoRepair::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoRepairPhase)OpInt(line, "aPhase", ARP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autorepair.h b/src/object/auto/autorepair.h new file mode 100644 index 0000000..1383fc7 --- /dev/null +++ b/src/object/auto/autorepair.h @@ -0,0 +1,76 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autorepair.h + +#ifndef _AUTOREPAIR_H_ +#define _AUTOREPAIR_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoRepairPhase +{ + ARP_WAIT = 1, // expected metal + ARP_DOWN = 2, // down the cover + ARP_REPAIR = 3, // repair the vehicle + ARP_UP = 4, // back cover + +}; + + + +class CAutoRepair : public CAuto +{ +public: + CAutoRepair(CInstanceManager* iMan, CObject* object); + ~CAutoRepair(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + CObject* SearchVehicle(); + +protected: + AutoRepairPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; +}; + + +#endif //_AUTOREPAIR_H_ diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp new file mode 100644 index 0000000..b15a9b8 --- /dev/null +++ b/src/object/auto/autoresearch.cpp @@ -0,0 +1,627 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "gauge.h" +#include "window.h" +#include "displaytext.h" +#include "sound.h" +#include "robotmain.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autoresearch.h" + + + +#define SEARCH_TIME 30.0f // duration of a research + + + +// Object's constructor. + +CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + int i; + + CAuto::CAuto(iMan, object); + + for ( i=0 ; i<6 ; i++ ) + { + m_partiStop[i] = -1; + } + m_channelSound = -1; + + Init(); +} + +// Object's destructor. + +CAutoResearch::~CAutoResearch() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoResearch::DeleteObject(BOOL bAll) +{ + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + FireStopUpdate(0.0f, FALSE); + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoResearch::Init() +{ + m_phase = ALP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; +} + + +// Management of an event. + +BOOL CAutoResearch::EventProcess(const Event &event) +{ + CObject* power; + D3DVECTOR pos, speed; + Error message; + FPOINT dim; + float angle, time; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + + if ( event.event == EVENT_UPDINTERFACE ) + { + if ( m_object->RetSelect() ) CreateInterface(TRUE); + } + + if ( m_object->RetSelect() && // center selected? + (event.event == EVENT_OBJECT_RTANK || + event.event == EVENT_OBJECT_RFLY || + event.event == EVENT_OBJECT_RTHUMP || + event.event == EVENT_OBJECT_RCANON || + event.event == EVENT_OBJECT_RTOWER || + event.event == EVENT_OBJECT_RPHAZER || + event.event == EVENT_OBJECT_RSHIELD || + event.event == EVENT_OBJECT_RATOMIC ) ) + { + if ( m_phase != ALP_WAIT ) + { + return FALSE; + } + + m_research = event.event; + + if ( TestResearch(m_research) ) + { + m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object); + return FALSE; + } + + power = m_object->RetPower(); + if ( power == 0 ) + { + m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object); + return FALSE; + } + if ( power->RetCapacity() > 1.0f ) + { + m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object); + return FALSE; + } + if ( power->RetEnergy() < 1.0f ) + { + m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object); + return FALSE; + } + + time = SEARCH_TIME; + if ( event.event == EVENT_OBJECT_RTANK ) time *= 0.3f; + if ( event.event == EVENT_OBJECT_RFLY ) time *= 0.3f; + if ( event.event == EVENT_OBJECT_RATOMIC ) time *= 2.0f; + + SetBusy(TRUE); + InitProgressTotal(time); + UpdateInterface(); + + m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->RetPosition(0), 0.0f, 1.0f, TRUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP); + + m_phase = ALP_SEARCH; + m_progress = 0.0f; + m_speed = 1.0f/time; + return TRUE; + } + + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + UpdateInterface(event.rTime); + EventProgress(event.rTime); + + angle = m_time*0.1f; + m_object->SetAngleY(1, angle); // rotates the antenna + + angle = (30.0f+sinf(m_time*0.3f)*20.0f)*PI/180.0f; + m_object->SetAngleZ(2, angle); // directs the antenna + + if ( m_phase == ALP_WAIT ) + { + FireStopUpdate(m_progress, FALSE); // extinguished + return TRUE; + } + + if ( m_phase == ALP_SEARCH ) + { + FireStopUpdate(m_progress, TRUE); // flashes + if ( m_progress < 1.0f ) + { + power = m_object->RetPower(); + if ( power == 0 ) // more battery? + { + SetBusy(FALSE); + UpdateInterface(); + + m_phase = ALP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + return TRUE; + } + power->SetEnergy(1.0f-m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*6.0f; + pos.z += (Rand()-0.5f)*6.0f; + pos.y += 11.0f; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = (Rand()-0.5f)*2.0f; + speed.y = Rand()*20.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR); + } + } + else + { + SetResearch(m_research); // research done + m_displayText->DisplayError(INFO_RESEARCH, m_object); + + message = ERR_OK; + if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK; + if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY; + if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP; + if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON; + if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER; + if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER; + if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD; + if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC; + if ( message != ERR_OK ) + { + m_displayText->DisplayError(message, m_object); + } + + SetBusy(FALSE); + UpdateInterface(); + + m_phase = ALP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoResearch::RetError() +{ + CObject* power; + + if ( m_phase == ALP_SEARCH ) + { + return ERR_OK; + } + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + power = m_object->RetPower(); + if ( power == 0 ) + { + return ERR_RESEARCH_POWER; + } + if ( power != 0 && power->RetCapacity() > 1.0f ) + { + return ERR_RESEARCH_TYPE; + } + if ( power != 0 && power->RetEnergy() < 1.0f ) + { + return ERR_RESEARCH_ENERGY; + } + + return ERR_OK; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoResearch::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK); + + pos.x = ox+sx*8.0f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY); + + pos.x = ox+sx*9.0f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON); + + pos.x = ox+sx*10.0f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER); + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC); + + pos.x = ox+sx*8.0f; + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP); + + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD); + + pos.x = ox+sx*10.0f; + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER); + + pos.x = ox+sx*14.5f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE); + + UpdateInterface(); + + return TRUE; +} + +// Updates the status of all interface buttons. + +void CAutoResearch::UpdateInterface() +{ + CWindow* pw; + + if ( !m_object->RetSelect() ) return; + + CAuto::UpdateInterface(); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK); + DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY); + DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP); + DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON); + DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER); + DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER); + DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD); + DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC); + + OkayButton(pw, EVENT_OBJECT_RTANK); + OkayButton(pw, EVENT_OBJECT_RFLY); + OkayButton(pw, EVENT_OBJECT_RTHUMP); + OkayButton(pw, EVENT_OBJECT_RCANON); + OkayButton(pw, EVENT_OBJECT_RTOWER); + OkayButton(pw, EVENT_OBJECT_RPHAZER); + OkayButton(pw, EVENT_OBJECT_RSHIELD); + OkayButton(pw, EVENT_OBJECT_RATOMIC); + + VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy); +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAutoResearch::UpdateInterface(float rTime) +{ + CWindow* pw; + CGauge* pg; + CObject* power; + float energy; + + CAuto::UpdateInterface(rTime); + + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY); + if ( pg != 0 ) + { + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + pg->SetLevel(energy); + } +} + +// Research shows already performed button. + +void CAutoResearch::OkayButton(CWindow *pw, EventMsg event) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_OKAY, TestResearch(event)); +} + + +// Test whether a search has already been done. + +BOOL CAutoResearch::TestResearch(EventMsg event) +{ + if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK ); + if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY ); + if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP ); + if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON ); + if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER ); + if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER ); + if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD); + if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC); + + return FALSE; +} + +// Indicates a search as made. + +void CAutoResearch::SetResearch(EventMsg event) +{ + Event newEvent; + + if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK; + if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY; + if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP; + if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON; + if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER; + if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER; + if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD; + if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC; + + m_main->WriteFreeParam(); + + m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE); + m_event->AddEvent(newEvent); + UpdateInterface(); +} + + +// Updates the stop lights. + +void CAutoResearch::FireStopUpdate(float progress, BOOL bLightOn) +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed; + FPOINT dim; + int i; + + static float listpos[12] = + { + 9.5f, 0.0f, + 4.7f, 8.2f, + -4.7f, 8.2f, + -9.5f, 0.0f, + -4.7f, -8.2f, + 4.7f, -8.2f, + }; + + if ( !bLightOn ) // �teint ? + { + for ( i=0 ; i<6 ; i++ ) + { + if ( m_partiStop[i] != -1 ) + { + m_particule->DeleteParticule(m_partiStop[i]); + m_partiStop[i] = -1; + } + } + return; + } + + mat = m_object->RetWorldMatrix(0); + + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f; + dim.y = dim.x; + + for ( i=0 ; i<6 ; i++ ) + { + if ( Mod(progress, 0.025f) < 0.005f ) + { + if ( m_partiStop[i] != -1 ) + { + m_particule->DeleteParticule(m_partiStop[i]); + m_partiStop[i] = -1; + } + } + else + { + if ( m_partiStop[i] == -1 ) + { + pos.x = listpos[i*2+0]; + pos.y = 11.5f; + pos.z = listpos[i*2+1]; + pos = Transform(*mat, pos); + m_partiStop[i] = m_particule->CreateParticule(pos, speed, + dim, PARTISELY, + 1.0f, 0.0f, 0.0f); + } + } + } +} + + +// Saves all parameters of the controller. + +BOOL CAutoResearch::Write(char *line) +{ + char name[100]; + + if ( m_phase == ALP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + sprintf(name, " aResearch=%d", m_research); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoResearch::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoResearchPhase)OpInt(line, "aPhase", ALP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + m_research = (EventMsg)OpInt(line, "aResearch", 0); + + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autoresearch.h b/src/object/auto/autoresearch.h new file mode 100644 index 0000000..f773084 --- /dev/null +++ b/src/object/auto/autoresearch.h @@ -0,0 +1,82 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoresearch.h + +#ifndef _AUTORESEARCH_H_ +#define _AUTORESEARCH_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoResearchPhase +{ + ALP_WAIT = 1, + ALP_SEARCH = 2, // research in progress +}; + + + +class CAutoResearch : public CAuto +{ +public: + CAutoResearch(CInstanceManager* iMan, CObject* object); + ~CAutoResearch(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(); + void UpdateInterface(float rTime); + void OkayButton(CWindow *pw, EventMsg event); + BOOL TestResearch(EventMsg event); + void SetResearch(EventMsg event); + void FireStopUpdate(float progress, BOOL bLightOn); + +protected: + AutoResearchPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastUpdateTime; + float m_lastParticule; + EventMsg m_research; + int m_partiStop[6]; + int m_channelSound; +}; + + +#endif //_AUTORESEARCH_H_ diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp new file mode 100644 index 0000000..5f1afad --- /dev/null +++ b/src/object/auto/autoroot.cpp @@ -0,0 +1,135 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "auto.h" +#include "autoroot.h" + + + + +// Object's constructor. + +CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoRoot::~CAutoRoot() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoRoot::DeleteObject(BOOL bAll) +{ + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoRoot::Init() +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed; + FPOINT dim; + + m_time = 0.0f; + m_lastParticule = 0.0f; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(-5.0f, 28.0f, -4.0f); // peak position + pos = Transform(*mat, pos); + m_center = pos; + + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 100.0f; + dim.y = dim.x; + m_particule->CreateParticule(m_center, speed, dim, PARTISPHERE5, 0.5f, 0.0f, 0.0f); + + m_terrain->AddFlyingLimit(pos, 100.0f, 80.0f, pos.y-60.0f); +} + + +// Management of an event. + +BOOL CAutoRoot::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed; + FPOINT dim; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_object->SetZoomX(1, 1.0f+sinf(m_time*2.0f)*0.2f); + m_object->SetZoomY(1, 1.0f+sinf(m_time*2.3f)*0.2f); + m_object->SetZoomZ(1, 1.0f+sinf(m_time*2.7f)*0.2f); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_center; + pos.x += (Rand()-0.5f)*8.0f; + pos.z += (Rand()-0.5f)*8.0f; + pos.y += 0.0f; + speed.x = (Rand()-0.5f)*12.0f; + speed.z = (Rand()-0.5f)*12.0f; + speed.y = Rand()*12.0f; + dim.x = Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIROOT, 1.0f, 0.0f, 0.0f); + } + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoRoot::RetError() +{ + return ERR_OK; +} + + diff --git a/src/object/auto/autoroot.h b/src/object/auto/autoroot.h new file mode 100644 index 0000000..85bdb69 --- /dev/null +++ b/src/object/auto/autoroot.h @@ -0,0 +1,56 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autoroot.h + +#ifndef _AUTOROOT_H_ +#define _AUTOROOT_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +class CAutoRoot : public CAuto +{ +public: + CAutoRoot(CInstanceManager* iMan, CObject* object); + ~CAutoRoot(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + +protected: + +protected: + float m_lastParticule; + D3DVECTOR m_center; +}; + + +#endif //_AUTOROOT_H_ diff --git a/src/object/auto/autosafe.cpp b/src/object/auto/autosafe.cpp new file mode 100644 index 0000000..bdc6d32 --- /dev/null +++ b/src/object/auto/autosafe.cpp @@ -0,0 +1,636 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "robotmain.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autosafe.h" + + + +#define OPEN_DELAY 8.0f // duration of opening + + + + +// Object's constructor. + +CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + int i; + + CAuto::CAuto(iMan, object); + + for ( i=0 ; i<4 ; i++ ) + { + m_bKey[i] = FALSE; + m_keyParti[i] = -1; + } + + m_bLock = FALSE; + m_lastParticule = 0.0f; + m_channelSound = -1; + Init(); +} + +// Object's destructor. + +CAutoSafe::~CAutoSafe() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoSafe::DeleteObject(BOOL bAll) +{ + CObject* pObj; + + pObj = SearchVehicle(); + if ( pObj != 0 ) + { + pObj->DeleteObject(); + delete pObj; + } + + if ( m_channelSound != -1 ) + { + m_sound->FlushEnvelope(m_channelSound); + m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_channelSound = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoSafe::Init() +{ + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastParticule = 0.0f; + + m_countKeys = 0; + m_actualAngle = 0.0f; + m_finalAngle = 0.0f; + + m_phase = ASAP_WAIT; // waiting ... + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoSafe::EventProcess(const Event &event) +{ + CObject* pObj; + D3DVECTOR pos, speed; + FPOINT dim; + int i, count; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + } + return TRUE; + } + + EventProgress(event.rTime); + + if ( !m_bLock ) + { + pObj = SearchVehicle(); + if ( pObj != 0 ) + { + pObj->SetLock(TRUE); // object not yet usable + m_main->CreateShortcuts(); + m_bLock = TRUE; + } + } + + if ( m_phase == ASAP_WAIT ) + { + if ( m_progress >= 1.0f ) + { + count = CountKeys(); // count these key + if ( count != m_countKeys ) + { + m_countKeys = count; + + if ( count == 0 ) m_finalAngle = 0.0f*PI/180.0f; + if ( count == 1 ) m_finalAngle = 5.0f*PI/180.0f; + if ( count == 2 ) m_finalAngle = 10.0f*PI/180.0f; + if ( count == 3 ) m_finalAngle = 15.0f*PI/180.0f; + if ( count == 4 ) m_finalAngle = 120.0f*PI/180.0f; + + if ( count == 4 ) // all the keys? + { + LockKeys(); + + m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, TRUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 2.00f, OPEN_DELAY, SOPER_STOP); + + m_phase = ASAP_OPEN; + m_progress = 0.0f; + m_speed = 1.0f/OPEN_DELAY; + return TRUE; + } + else + { + m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, TRUE); + m_sound->AddEnvelope(m_channelSound, 1.0f, 0.35f, 0.5f, SOPER_STOP); + } + } + + m_phase = ASAP_WAIT; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ASAP_OPEN ) + { + if ( m_progress < 1.0f ) + { + DownKeys(m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + for ( i=0 ; i<10 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + speed.x = (Rand()-0.5f)*4.0f; + speed.z = (Rand()-0.5f)*4.0f; + speed.y = Rand()*15.0f; + dim.x = Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); + } + + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + speed.x = (Rand()-0.5f)*4.0f; + speed.z = (Rand()-0.5f)*4.0f; + speed.y = Rand()*10.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f); + + for ( i=0 ; i<4 ; i++ ) + { + pos = m_keyPos[i]; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = (Rand()-0.5f)*2.0f; + speed.y = 1.0f+Rand()*1.0f; + dim.x = Rand()*1.5f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f); + } + } + } + else + { + DeleteKeys(); + + pObj = SearchVehicle(); + if ( pObj != 0 ) + { + pObj->SetLock(FALSE); // object usable + m_main->CreateShortcuts(); + } + + m_object->FlushCrashShere(); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 0.0f); + + m_sound->Play(SOUND_FINDING, m_object->RetPosition(0)); + + m_phase = ASAP_FINISH; + m_progress = 0.0f; + m_speed = 1.0f/100.0f; + } + } + + if ( m_phase == ASAP_FINISH ) + { + if ( m_progress >= 1.0f ) + { + m_phase = ASAP_FINISH; + m_progress = 0.0f; + m_speed = 1.0f/100.0f; + } + } + + // Opens or closes the doors. + if ( m_actualAngle != m_finalAngle ) + { + if ( m_actualAngle < m_finalAngle ) + { + m_actualAngle += (105.0f*PI/180.0f)*event.rTime/OPEN_DELAY; + if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle; + } + else + { + m_actualAngle -= (105.0f*PI/180.0f)*event.rTime/OPEN_DELAY; + if ( m_actualAngle < m_finalAngle ) m_actualAngle = m_finalAngle; + } + m_object->SetAngleZ(1, m_actualAngle); + m_object->SetAngleZ(2, -m_actualAngle); + } + + // Blinks the keys. + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f; + dim.y = dim.x; + for ( i=0 ; i<4 ; i++ ) + { + if ( m_phase != ASAP_WAIT || !m_bKey[i] || Mod(m_time, 1.0f) < 0.4f ) + { + if ( m_keyParti[i] != -1 ) + { + m_particule->DeleteParticule(m_keyParti[i]); + m_keyParti[i] = -1; + } + } + else + { + if ( m_keyParti[i] == -1 ) + { + pos = m_keyPos[i]; + pos.y += 2.2f; + m_keyParti[i] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f); + } + } + } + + return TRUE; +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoSafe::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 114, EVENT_OBJECT_TYPE); + + return TRUE; +} + + +// Returns an error due the state of the automation. + +Error CAutoSafe::RetError() +{ + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + return ERR_OK; +} + + +// Saves all parameters of the controller. + +BOOL CAutoSafe::Write(char *line) +{ + char name[100]; + + if ( m_phase == ASAP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoSafe::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoSafePhase)OpInt(line, "aPhase", ASAP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + + m_lastParticule = 0.0f; + + return TRUE; +} + + +// Counts the number of keys + +int CAutoSafe::CountKeys() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + FPOINT rot; + ObjectType oType; + float dist, angle, limit, cAngle, oAngle; + int i, index; + + cPos = m_object->RetPosition(0); + cAngle = m_object->RetAngleY(0); + + for ( index=0 ; index<4 ; index++ ) + { + m_bKey[index] = FALSE; + m_keyPos[index] = cPos; + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( pObj->RetTruck() != 0 ) continue; + + if ( oType != OBJECT_KEYa && + oType != OBJECT_KEYb && + oType != OBJECT_KEYc && + oType != OBJECT_KEYd ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist > 20.0f ) continue; + + if ( oType == OBJECT_KEYa ) + { + limit = PI*1.0f; + oAngle = PI*0.0f; + index = 0; + } + if ( oType == OBJECT_KEYb ) + { + limit = PI*0.0f; + oAngle = PI*1.0f; + index = 1; + } + if ( oType == OBJECT_KEYc ) + { + limit = PI*1.5f; + oAngle = PI*0.5f; + index = 2; + } + if ( oType == OBJECT_KEYd ) + { + limit = PI*0.5f; + oAngle = PI*0.0f; + index = 3; + } + + angle = RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle; + if ( !TestAngle(angle, limit-8.0f*PI/180.0f, limit+8.0f*PI/180.0f) ) continue; + + // Key changes the shape of the base. + rot = RotatePoint(FPOINT(cPos.x, cPos.z), limit-cAngle, FPOINT(cPos.x+16.0f, cPos.z)); + oPos.x = rot.x; + oPos.z = rot.y; + oPos.y = cPos.y+1.0f; + pObj->SetPosition(0, oPos); + pObj->SetAngleY(0, oAngle+cAngle); + m_keyPos[index] = oPos; + + m_bKey[index] = TRUE; + } + + i = 0; + for ( index=0 ; index<4 ; index++ ) + { + if ( m_bKey[index] ) i++; + } + return i; +} + +// Blocks all keys. + +void CAutoSafe::LockKeys() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType oType; + float dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( pObj->RetTruck() != 0 ) continue; + + if ( oType != OBJECT_KEYa && + oType != OBJECT_KEYb && + oType != OBJECT_KEYc && + oType != OBJECT_KEYd ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist > 20.0f ) continue; + + pObj->SetLock(TRUE); + } +} + +// Sent down all the keys. + +void CAutoSafe::DownKeys(float progress) +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType oType; + float dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( pObj->RetTruck() != 0 ) continue; + + if ( oType != OBJECT_KEYa && + oType != OBJECT_KEYb && + oType != OBJECT_KEYc && + oType != OBJECT_KEYd ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist > 20.0f ) continue; + + oPos.y = cPos.y+1.0f-progress*2.2f; + pObj->SetPosition(0, oPos); + } +} + +// Delete all the keys. + +void CAutoSafe::DeleteKeys() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType oType; + float dist; + int i; + BOOL bDelete; + + cPos = m_object->RetPosition(0); + + do + { + bDelete = FALSE; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( pObj->RetTruck() != 0 ) continue; + + if ( oType != OBJECT_KEYa && + oType != OBJECT_KEYb && + oType != OBJECT_KEYc && + oType != OBJECT_KEYd ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist > 20.0f ) continue; + + pObj->DeleteObject(); + delete pObj; + bDelete = TRUE; + } + } + while ( bDelete ); +} + +// Seeking a vehicle in the safe. + +CObject* CAutoSafe::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR cPos, oPos; + ObjectType oType; + float dist; + int i; + + cPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, cPos); + if ( dist <= 4.0f ) return pObj; + } + return 0; +} + + + diff --git a/src/object/auto/autosafe.h b/src/object/auto/autosafe.h new file mode 100644 index 0000000..b60472d --- /dev/null +++ b/src/object/auto/autosafe.h @@ -0,0 +1,86 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autosafe.h + +#ifndef _AUTOSAFE_H_ +#define _AUTOSAFE_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoSafePhase +{ + ASAP_WAIT = 1, + ASAP_OPEN = 2, + ASAP_FINISH = 3, +}; + + + +class CAutoSafe : public CAuto +{ +public: + CAutoSafe(CInstanceManager* iMan, CObject* object); + ~CAutoSafe(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + int CountKeys(); + void LockKeys(); + void DownKeys(float progress); + void DeleteKeys(); + CObject* SearchVehicle(); + +protected: + AutoSafePhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastParticule; + int m_channelSound; + BOOL m_bLock; + int m_countKeys; + float m_actualAngle; + float m_finalAngle; + BOOL m_bKey[4]; + D3DVECTOR m_keyPos[4]; + int m_keyParti[4]; +}; + + +#endif //_AUTOSAFE_H_ diff --git a/src/object/auto/autostation.cpp b/src/object/auto/autostation.cpp new file mode 100644 index 0000000..1e23e1d --- /dev/null +++ b/src/object/auto/autostation.cpp @@ -0,0 +1,387 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "light.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "interface.h" +#include "button.h" +#include "gauge.h" +#include "window.h" +#include "sound.h" +#include "auto.h" +#include "autostation.h" + + + + +// Object's constructor. + +CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + CAuto::CAuto(iMan, object); + + Init(); +} + +// Object's destructor. + +CAutoStation::~CAutoStation() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoStation::DeleteObject(BOOL bAll) +{ + if ( m_soundChannel != -1 ) + { + m_sound->Stop(m_soundChannel); + m_soundChannel = -1; + } + + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoStation::Init() +{ + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; + m_soundChannel = -1; + m_bLastVirus = FALSE; + + CAuto::Init(); +} + + +// Management of an event. + +BOOL CAutoStation::EventProcess(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR pos, ppos, speed; + FPOINT dim; + CObject* vehicule; + CObject* power; + TerrainRes res; + float big, energy, used, add, freq; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( !m_bLastVirus ) + { + m_bLastVirus = TRUE; + m_energyVirus = m_object->RetEnergy(); + } + + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + m_object->SetEnergy(Rand()); + } + return TRUE; + } + else + { + if ( m_bLastVirus ) + { + m_bLastVirus = FALSE; + m_object->SetEnergy(m_energyVirus); + } + } + + UpdateInterface(event.rTime); + + big = m_object->RetEnergy(); + + res = m_terrain->RetResource(m_object->RetPosition(0)); + if ( res == TR_POWER ) + { + big += event.rTime*0.01f; // recharges the large battery + } + + used = big; + freq = 1.0f; + if ( big > 0.0f ) + { + vehicule = SearchVehicle(); + if ( vehicule != 0 ) + { + power = vehicule->RetPower(); + if ( power != 0 && power->RetCapacity() == 1.0f ) + { + energy = power->RetEnergy(); + add = event.rTime*0.2f; + if ( add > big*4.0f ) add = big*4.0f; + if ( add > 1.0f-energy ) add = 1.0f-energy; + energy += add; // Charging the battery + power->SetEnergy(energy); + if ( energy < freq ) freq = energy; + big -= add/4.0f; // discharge the large battery + } + + power = vehicule->RetFret(); + if ( power != 0 && power->RetType() == OBJECT_POWER ) + { + energy = power->RetEnergy(); + add = event.rTime*0.2f; + if ( add > big*4.0f ) add = big*4.0f; + if ( add > 1.0f-energy ) add = 1.0f-energy; + energy += add; // Charging the battery + power->SetEnergy(energy); + if ( energy < freq ) freq = energy; + big -= add/4.0f; // discharge the large battery + } + } + } + used -= big; // energy used + + if ( freq < 1.0f ) // charging in progress? + { + freq = 1.0f+3.0f*freq; + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_STATION, m_object->RetPosition(0), + 0.3f, freq, TRUE); + } + m_sound->Frequency(m_soundChannel, freq); + } + else + { + if ( m_soundChannel != -1 ) + { + m_sound->Stop(m_soundChannel); + m_soundChannel = -1; + } + } + + if ( used != 0.0f && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(-15.0f, 7.0f, 0.0f); // battery position + pos = Transform(*mat, pos); + speed.x = (Rand()-0.5f)*20.0f; + speed.y = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + ppos.x = pos.x; + ppos.y = pos.y+(Rand()-0.5f)*4.0f; + ppos.z = pos.z; + dim.x = 1.5f; + dim.y = 1.5f; + m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f); + +#if 0 + ppos = pos; + ppos.y += 1.0f; + ppos.x += (Rand()-0.5f)*3.0f; + ppos.z += (Rand()-0.5f)*3.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 2.5f+Rand()*6.0f; + dim.x = Rand()*1.5f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(ppos, speed, dim, PARTISMOKE3, 4.0f); +#else + ppos = pos; + ppos.y += 1.0f; + ppos.x += (Rand()-0.5f)*3.0f; + ppos.z += (Rand()-0.5f)*3.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 2.5f+Rand()*5.0f; + dim.x = Rand()*1.0f+0.6f; + dim.y = dim.x; + m_particule->CreateParticule(ppos, speed, dim, PARTIVAPOR, 3.0f); +#endif + } + + if ( big < 0.0f ) big = 0.0f; + if ( big > 1.0f ) big = 1.0f; + m_object->SetEnergy(big); // Shift the large battery + + return TRUE; +} + + +// Seeking the vehicle on the station. + +CObject* CAutoStation::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR sPos, oPos; + ObjectType type; + float dist; + int i; + + sPos = m_object->RetPosition(0); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, sPos); + if ( dist <= 5.0f ) return pObj; + } + + return 0; +} + + +// Returns an error due the state of the automation. + +Error CAutoStation::RetError() +{ + TerrainRes res; + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + res = m_terrain->RetResource(m_object->RetPosition(0)); + if ( res != TR_POWER ) return ERR_STATION_NULL; + + return ERR_OK; +} + + +// Crée toute l'interface lorsque l'objet est sélectionné . + +BOOL CAutoStation::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*14.5f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 104, EVENT_OBJECT_TYPE); + + return TRUE; +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAutoStation::UpdateInterface(float rTime) +{ + CWindow* pw; + CGauge* pg; + + CAuto::UpdateInterface(rTime); + + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY); + if ( pg != 0 ) + { + pg->SetLevel(m_object->RetEnergy()); + } +} + + diff --git a/src/object/auto/autostation.h b/src/object/auto/autostation.h new file mode 100644 index 0000000..d783cc9 --- /dev/null +++ b/src/object/auto/autostation.h @@ -0,0 +1,68 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autostation.h + +#ifndef _AUTOSTATION_H_ +#define _AUTOSTATION_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +class CAutoStation : public CAuto +{ +public: + CAutoStation(CInstanceManager* iMan, CObject* object); + ~CAutoStation(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + +protected: + void UpdateInterface(float rTime); + + CObject* SearchVehicle(); + +protected: + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastUpdateTime; + float m_lastParticule; + int m_soundChannel; + D3DVECTOR m_fretPos; + BOOL m_bLastVirus; + float m_energyVirus; +}; + + +#endif //_AUTOSTATION_H_ diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp new file mode 100644 index 0000000..7dcdb05 --- /dev/null +++ b/src/object/auto/autotower.cpp @@ -0,0 +1,561 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "math3d.h" +#include "particule.h" +#include "terrain.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "interface.h" +#include "button.h" +#include "gauge.h" +#include "window.h" +#include "sound.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "auto.h" +#include "autotower.h" + + + +#define TOWER_SCOPE 200.0f // range of beam +#define ENERGY_FIRE 0.125f // energy consumed by fire + + +// Object's constructor. + +CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object) + : CAuto(iMan, object) +{ + int i; + + CAuto::CAuto(iMan, object); + + for ( i=0 ; i<4 ; i++ ) + { + m_partiStop[i] = -1; + } + + Init(); + m_phase = ATP_WAIT; // paused until the first Init () + m_time = 0.0f; + m_lastUpdateTime = 0.0f; +} + +// Object's destructor. + +CAutoTower::~CAutoTower() +{ + this->CAuto::~CAuto(); +} + + +// Destroys the object. + +void CAutoTower::DeleteObject(BOOL bAll) +{ + FireStopUpdate(0.0f, FALSE); + CAuto::DeleteObject(bAll); +} + + +// Initialize the object. + +void CAutoTower::Init() +{ + m_phase = ATP_ZERO; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + + m_time = 0.0f; + m_timeVirus = 0.0f; + m_lastUpdateTime = 0.0f; + m_lastParticule = 0.0f; +} + + +// Management of an event. + +BOOL CAutoTower::EventProcess(const Event &event) +{ + CObject* power; + CObject* target; + D3DVECTOR pos; + float angle, energy, quick; + + CAuto::EventProcess(event); + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_timeVirus -= event.rTime; + + if ( m_object->RetVirusMode() ) // contaminated by a virus? + { + if ( m_timeVirus <= 0.0f ) + { + m_timeVirus = 0.1f+Rand()*0.3f; + + angle = m_object->RetAngleY(1); + angle += Rand()*0.5f; + m_object->SetAngleY(1, angle); + + m_object->SetAngleZ(2, Rand()*0.5f); + } + return TRUE; + } + + UpdateInterface(event.rTime); + + if ( m_phase == ATP_WAIT ) return TRUE; + + m_progress += event.rTime*m_speed; + + if ( m_phase == ATP_ZERO ) + { + FireStopUpdate(m_progress, TRUE); // blinks + if ( m_progress < 1.0f ) + { + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + if ( energy >= ENERGY_FIRE ) + { + m_phase = ATP_SEARCH; + m_progress = 0.0f; + m_speed = 1.0f/3.0f; + } + } + else + { + m_phase = ATP_ZERO; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + if ( m_phase == ATP_SEARCH ) + { + FireStopUpdate(m_progress, FALSE); // extinguished + if ( m_progress < 1.0f ) + { + quick = 1.0f; +//? if ( g_researchDone & RESEARCH_QUICK ) quick = 3.0f; + + angle = m_object->RetAngleY(1); + angle -= event.rTime*quick*2.0f; + m_object->SetAngleY(1, angle); + + angle = m_object->RetAngleZ(2); + angle += event.rTime*quick*0.5f; + if ( angle > 0.0f ) angle = 0.0f; + m_object->SetAngleZ(2, angle); + } + else + { + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + + target = SearchTarget(m_targetPos); + if ( energy < ENERGY_FIRE ) + { + m_displayText->DisplayError(ERR_TOWER_ENERGY, m_object); + } + if ( target == 0 || energy < ENERGY_FIRE ) + { + m_phase = ATP_ZERO; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + else + { + pos = m_object->RetPosition(0); + pos.y += 24.5f; + m_angleYfinal = RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW ! + m_angleYfinal += PI*2.0f; + m_angleYfinal -= m_object->RetAngleY(0); + m_angleYactual = NormAngle(m_object->RetAngleY(1)); + + m_angleZfinal = -PI/2.0f; + m_angleZfinal -= RotateAngle(Length2d(m_targetPos, pos), pos.y-m_targetPos.y); // CW ! + m_angleZactual = m_object->RetAngleZ(2); + + m_phase = ATP_TURN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; +//? if ( g_researchDone & RESEARCH_QUICK ) m_speed = 1.0f/0.2f; + } + } + } + + if ( m_phase == ATP_TURN ) + { + if ( m_progress < 1.0f ) + { + angle = m_angleYactual+(m_angleYfinal-m_angleYactual)*m_progress; + m_object->SetAngleY(1, angle); + + angle = m_angleZactual+(m_angleZfinal-m_angleZactual)*m_progress; + m_object->SetAngleZ(2, angle); + } + else + { + m_object->SetAngleY(1, m_angleYfinal); + m_object->SetAngleZ(2, m_angleZfinal); + + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + energy -= ENERGY_FIRE/power->RetCapacity(); + power->SetEnergy(energy); + } + + m_sound->Play(SOUND_GGG, m_object->RetPosition(0)); + + m_phase = ATP_FIRE; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + } + } + + if ( m_phase == ATP_FIRE ) + { + if ( m_progress == 0.0f ) + { + pos = m_object->RetPosition(0); + pos.y += 24.5f; + m_particule->CreateRay(pos, m_targetPos, PARTIRAY1, + FPOINT(5.0f, 5.0f), 1.5f); + } + if ( m_progress >= 1.0f ) + { + m_phase = ATP_ZERO; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + } + } + + return TRUE; +} + + +// Seeks the nearest target object. + +CObject* CAutoTower::SearchTarget(D3DVECTOR &impact) +{ + CObject* pObj; + CObject* pBest = 0; + CPhysics* physics; + D3DVECTOR iPos, oPos; + ObjectType oType; + float distance, min, radius, speed; + int i; + + iPos = m_object->RetPosition(0); + min = 1000000.0f; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( oType != OBJECT_MOTHER && + oType != OBJECT_ANT && + oType != OBJECT_SPIDER && + oType != OBJECT_BEE && + oType != OBJECT_WORM ) continue; + + if ( !pObj->RetActif() ) continue; // inactive? + +//? if ( g_researchDone & RESEARCH_QUICK ) + if ( FALSE ) + { + physics = pObj->RetPhysics(); + if ( physics != 0 ) + { + speed = Abs(physics->RetLinMotionX(MO_REASPEED)); + if ( speed > 20.0f ) continue; // moving too fast? + } + } + + if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue; + distance = Length(oPos, iPos); + if ( distance > TOWER_SCOPE ) continue; // too far + if ( distance < min ) + { + min = distance; + pBest = pObj; + } + } + if ( pBest == 0 ) return 0; + + impact = pBest->RetPosition(0); + return pBest; +} + + +// Returns an error due the state of the automation. + +Error CAutoTower::RetError() +{ + CObject* power; + + if ( m_object->RetVirusMode() ) + { + return ERR_BAT_VIRUS; + } + + power = m_object->RetPower(); + if ( power == 0 ) + { + return ERR_TOWER_POWER; // no battery + } + else + { + if ( power->RetEnergy() < ENERGY_FIRE ) + { + return ERR_TOWER_ENERGY; // not enough energy + } + } + return ERR_OK; +} + + +// Updates the stop lights. + +void CAutoTower::FireStopUpdate(float progress, BOOL bLightOn) +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed; + FPOINT dim; + int i; + + static float listpos[8] = + { + 4.5f, 0.0f, + 0.0f, 4.5f, + -4.5f, 0.0f, + 0.0f, -4.5f, + }; + + if ( !bLightOn ) // extinguished? + { + for ( i=0 ; i<4 ; i++ ) + { + if ( m_partiStop[i] != -1 ) + { + m_particule->DeleteParticule(m_partiStop[i]); + m_partiStop[i] = -1; + } + } + return; + } + + mat = m_object->RetWorldMatrix(0); + + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f; + dim.y = dim.x; + + for ( i=0 ; i<4 ; i++ ) + { + if ( Mod(progress+i*0.125f, 0.5f) < 0.2f ) + { + if ( m_partiStop[i] != -1 ) + { + m_particule->DeleteParticule(m_partiStop[i]); + m_partiStop[i] = -1; + } + } + else + { + if ( m_partiStop[i] == -1 ) + { + pos.x = listpos[i*2+0]; + pos.y = 18.0f; + pos.z = listpos[i*2+1]; + pos = Transform(*mat, pos); + m_partiStop[i] = m_particule->CreateParticule(pos, speed, + dim, PARTISELR, + 1.0f, 0.0f, 0.0f); + } + } + } +} + + +// Creates all the interface when the object is selected. + +BOOL CAutoTower::CreateInterface(BOOL bSelect) +{ + CWindow* pw; + FPOINT pos, ddim; + float ox, oy, sx, sy; + + CAuto::CreateInterface(bSelect); + + if ( !bSelect ) return TRUE; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + pos.x = ox+sx*14.5f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0; + ddim.x = 66.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 107, EVENT_OBJECT_TYPE); + + pos.x = ox+sx*10.2f; + pos.y = oy+sy*0.5f; + ddim.x = 33.0f/640.0f; + ddim.y = 33.0f/480.0f; + pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT); + + return TRUE; +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CAutoTower::UpdateInterface(float rTime) +{ + CWindow* pw; + CGauge* pg; + CObject* power; + float energy; + + CAuto::UpdateInterface(rTime); + + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY); + if ( pg != 0 ) + { + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + pg->SetLevel(energy); + } +} + + +// Saves all parameters of the controller. + +BOOL CAutoTower::Write(char *line) +{ + char name[100]; + + if ( m_phase == ATP_WAIT ) return FALSE; + + sprintf(name, " aExist=%d", 1); + strcat(line, name); + + CAuto::Write(line); + + sprintf(name, " aPhase=%d", m_phase); + strcat(line, name); + + sprintf(name, " aProgress=%.2f", m_progress); + strcat(line, name); + + sprintf(name, " aSpeed=%.2f", m_speed); + strcat(line, name); + + sprintf(name, " aTargetPos=%.2f;%.2f;%.2f", m_targetPos.x, m_targetPos.y, m_targetPos.z); + strcat(line, name); + + sprintf(name, " aAngleYactual=%.2f", m_angleYactual); + strcat(line, name); + + sprintf(name, " aAngleZactual=%.2f", m_angleZactual); + strcat(line, name); + + sprintf(name, " aAngleYfinal=%.2f", m_angleYfinal); + strcat(line, name); + + sprintf(name, " aAngleZfinal=%.2f", m_angleZfinal); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the controller. + +BOOL CAutoTower::Read(char *line) +{ + if ( OpInt(line, "aExist", 0) == 0 ) return FALSE; + + CAuto::Read(line); + + m_phase = (AutoTowerPhase)OpInt(line, "aPhase", ATP_WAIT); + m_progress = OpFloat(line, "aProgress", 0.0f); + m_speed = OpFloat(line, "aSpeed", 1.0f); + m_targetPos = OpDir(line, "aTargetPos"); + m_angleYactual = OpFloat(line, "aAngleYactual", 0.0f); + m_angleZactual = OpFloat(line, "aAngleZactual", 0.0f); + m_angleYfinal = OpFloat(line, "aAngleYfinal", 0.0f); + m_angleZfinal = OpFloat(line, "aAngleZfinal", 0.0f); + + m_lastUpdateTime = 0.0f; + + return TRUE; +} + + diff --git a/src/object/auto/autotower.h b/src/object/auto/autotower.h new file mode 100644 index 0000000..fa7e6cb --- /dev/null +++ b/src/object/auto/autotower.h @@ -0,0 +1,86 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// autotower.h + +#ifndef _AUTOTOWER_H_ +#define _AUTOTOWER_H_ + + +#include "auto.h" +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CParticule; +class CTerrain; +class CCamera; +class CObject; + + + +enum AutoTowerPhase +{ + ATP_WAIT = 1, + ATP_ZERO = 2, // more energy + ATP_SEARCH = 3, // search a target + ATP_TURN = 4, // turns to the target + ATP_FIRE = 5, // shoots on the target +}; + + + +class CAutoTower : public CAuto +{ +public: + CAutoTower(CInstanceManager* iMan, CObject* object); + ~CAutoTower(); + + void DeleteObject(BOOL bAll=FALSE); + + void Init(); + BOOL EventProcess(const Event &event); + Error RetError(); + + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + +protected: + void UpdateInterface(float rTime); + + CObject* SearchTarget(D3DVECTOR &impact); + void FireStopUpdate(float progress, BOOL bLightOn); + +protected: + AutoTowerPhase m_phase; + float m_progress; + float m_speed; + float m_timeVirus; + float m_lastUpdateTime; + float m_lastParticule; + D3DVECTOR m_targetPos; + float m_angleYactual; + float m_angleZactual; + float m_angleYfinal; + float m_angleZfinal; + int m_partiStop[4]; +}; + + +#endif //_AUTOTOWER_H_ diff --git a/src/object/brain.cpp b/src/object/brain.cpp new file mode 100644 index 0000000..e942e5d --- /dev/null +++ b/src/object/brain.cpp @@ -0,0 +1,3000 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "CBot/CBotDll.h" +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "language.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "restext.h" +#include "math3d.h" +#include "robotmain.h" +#include "terrain.h" +#include "water.h" +#include "camera.h" +#include "object.h" +#include "physics.h" +#include "motion.h" +#include "motionspider.h" +#include "pyro.h" +#include "taskmanager.h" +#include "task.h" +#include "taskmanip.h" +#include "taskflag.h" +#include "taskshield.h" +#include "script.h" +#include "studio.h" +#include "interface.h" +#include "button.h" +#include "color.h" +#include "edit.h" +#include "list.h" +#include "label.h" +#include "group.h" +#include "gauge.h" +#include "slider.h" +#include "compass.h" +#include "target.h" +#include "window.h" +#include "displaytext.h" +#include "text.h" +#include "sound.h" +#include "particule.h" +#include "cmdtoken.h" +#include "brain.h" + + + +#define MAXTRACERECORD 1000 + + + +// Object's constructor. + +CBrain::CBrain(CInstanceManager* iMan, CObject* object) +{ + int i; + + m_iMan = iMan; + m_iMan->AddInstance(CLASS_BRAIN, this, 100); + + m_object = object; + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_physics = 0; + m_motion = 0; + m_primaryTask = 0; + m_secondaryTask = 0; + m_studio = 0; + + m_program = -1; + m_bActivity = TRUE; + m_bBurn = FALSE; + m_bActiveVirus = FALSE; + m_time = 0.0f; + m_burnTime = 0.0f; + m_lastUpdateTime = 0.0f; + m_lastHumanTime = 0.0f; + m_lastWormTime = 0.0f; + m_antTarget = 0; + m_beeBullet = 0; + m_lastAlarmTime = 0.0f; + m_soundChannelAlarm = -1; + m_flagColor = 0; + + m_buttonAxe = EVENT_NULL; + m_defaultEnter = EVENT_NULL; + m_manipStyle = EVENT_OBJECT_MFRONT; + + for ( i=0 ; iDeleteInstance(CLASS_BRAIN, this); +} + + +// Destroys the object. + +void CBrain::DeleteObject(BOOL bAll) +{ + if ( m_soundChannelAlarm != -1 ) + { + m_sound->FlushEnvelope(m_soundChannelAlarm); + m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP); + m_soundChannelAlarm = -1; + } + + if ( !bAll ) + { + if ( m_beeBullet != 0 ) + { + m_beeBullet->DeleteObject(); + delete m_beeBullet; + m_beeBullet = 0; + } + } + + if ( m_studio != 0 ) // current edition? + { + StopEditScript(TRUE); + } +} + + +void CBrain::SetPhysics(CPhysics* physics) +{ + m_physics = physics; +} + +void CBrain::SetMotion(CMotion* motion) +{ + m_motion = motion; +} + + +// Saves all parameters of the object. + +BOOL CBrain::Write(char *line) +{ + char name[100]; + + sprintf(name, " bVirusActive=%d", m_bActiveVirus); + strcat(line, name); + + return TRUE; +} + +// Restores all parameters of the object. + +BOOL CBrain::Read(char *line) +{ + m_bActiveVirus = OpInt(line, "bVirusActive", 0); + + return TRUE; +} + + +// Management of an event. + +BOOL CBrain::EventProcess(const Event &event) +{ + CWindow* pw; + CControl* pc; + CSlider* ps; + EventMsg action; + ObjectType type; + Error err; + float axeX, axeY, axeZ, factor; + + type = m_object->RetType(); + + if ( m_primaryTask != 0 ) // current task? + { + m_primaryTask->EventProcess(event); + } + + if ( m_secondaryTask != 0 ) // current task? + { + m_secondaryTask->EventProcess(event); + } + + action = EVENT_NULL; + + if ( event.event == EVENT_KEYDOWN && + (event.param == m_engine->RetKey(KEYRANK_ACTION, 0) || + event.param == m_engine->RetKey(KEYRANK_ACTION, 1) ) && + !m_main->RetEditLock() ) + { + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + pc = pw->SearchControl(m_defaultEnter); + if ( pc != 0 ) + { + if ( pc->TestState(STATE_ENABLE) ) + { + action = m_defaultEnter; + } + } + } + } + else + { + action = event.event; + } + + if ( action == EVENT_NULL ) return TRUE; + + if ( action == EVENT_UPDINTERFACE ) + { + if ( m_object->RetSelect() ) CreateInterface(TRUE); + } + + if ( action == EVENT_FRAME ) + { + EventFrame(event); + } + + if ( m_object->RetSelect() && // robot selected? + m_studio != 0 ) // current issue? + { + m_studio->EventProcess(event); + + if ( action == EVENT_OBJECT_PROGRUN ) + { + if ( m_program == -1 ) + { + RunProgram(m_selScript); + } + else + { + StopProgram(); + } + } + if ( action == EVENT_OBJECT_PROGSTART ) + { + m_main->SaveOneScript(m_object); + RunProgram(m_selScript); + } + if ( action == EVENT_OBJECT_PROGSTOP ) + { + StopProgram(); + } + if ( action == EVENT_STUDIO_OK ) + { + StopEditScript(FALSE); + m_main->SaveOneScript(m_object); + } + if ( action == EVENT_STUDIO_CANCEL ) + { + StopEditScript(TRUE); + m_main->SaveOneScript(m_object); + } + return TRUE; + } + + if ( !m_object->RetSelect() && // robot pas sélectionné ? + m_program == -1 && + m_primaryTask == 0 ) + { + axeX = 0.0f; + axeY = 0.0f; + axeZ = 0.0f; + if ( m_object->RetBurn() ) // Gifted? + { + if ( !m_bBurn ) // beginning? + { + m_bBurn = TRUE; + m_burnTime = 0.0f; + } + + axeZ = -1.0f; // tomb + + if ( !m_object->RetFixed() && + (type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_WORM ) ) + { + axeY = 2.0f; // zigzag disorganized fast + if ( type == OBJECT_WORM ) axeY = 5.0f; + axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+ + sinf(m_time* 6.0f)*2.0f+ + sinf(m_time*21.0f)*0.2f; + factor = 1.0f-m_burnTime/15.0f; // slow motion + if ( factor < 0.0f ) factor = 0.0f; + axeY *= factor; + axeX *= factor; + } + } + m_physics->SetMotorSpeedX(axeY); // move forward/move back + m_physics->SetMotorSpeedY(axeZ); // up / down + m_physics->SetMotorSpeedZ(axeX); // rotate + return TRUE; + } + + if ( m_program != -1 && + m_object->RetRuin() ) + { + StopProgram(); + return TRUE; + } + + if ( !m_object->RetSelect() ) // robot not selected? + { + return TRUE; + } + + if ( m_secondaryTask != 0 ) // current task? + { + if ( action == EVENT_OBJECT_ENDSHIELD ) + { + m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f); + } + } + if ( m_primaryTask != 0 || // current task? + m_program != -1 ) + { + if ( action == EVENT_OBJECT_PROGRUN ) + { + StopProgram(); + } + if ( action == EVENT_OBJECT_PROGEDIT ) + { + StartEditScript(m_selScript, m_main->RetScriptName()); + } + if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return TRUE; + } + + if ( action == EVENT_OBJECT_LEFT || + action == EVENT_OBJECT_RIGHT || + action == EVENT_OBJECT_UP || + action == EVENT_OBJECT_DOWN || + action == EVENT_OBJECT_GASUP || + action == EVENT_OBJECT_GASDOWN ) + { + m_buttonAxe = action; + } + if ( action == EVENT_LBUTTONUP || + action == EVENT_RBUTTONUP ) + { + m_buttonAxe = EVENT_NULL; + } + + axeX = event.axeX; + axeY = event.axeY; + axeZ = event.axeZ; + + if ( !m_main->RetTrainerPilot() && + m_object->RetTrainer() ) // drive vehicle? + { + axeX = 0.0f; + axeY = 0.0f; + axeZ = 0.0f; // Remote control impossible! + } + + if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f; + if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f; + if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f; + if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f; + + if ( m_object->RetManual() ) // scribbler in manual mode? + { + if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving! + axeX *= 0.5f; + axeY *= 0.5f; + } + + if ( (g_researchDone&RESEARCH_FLY) == 0 ) + { + axeZ = -1.0f; // tomb + } + + axeX += m_camera->RetMotorTurn(); // additional power according to camera + if ( axeX > 1.0f ) axeX = 1.0f; + if ( axeX < -1.0f ) axeX = -1.0f; + + m_physics->SetMotorSpeedX(axeY); // move forward/move back + m_physics->SetMotorSpeedY(axeZ); // up/down + m_physics->SetMotorSpeedZ(axeX); // rotate + + if ( action == EVENT_OBJECT_PROGLIST ) + { + m_selScript = RetSelScript(); + UpdateInterface(); + } + + if ( action == EVENT_OBJECT_PROGEDIT ) + { + StartEditScript(m_selScript, m_main->RetScriptName()); + } + + if ( action == EVENT_OBJECT_PROGRUN ) + { + StopProgram(); // stops the current program + RunProgram(m_selScript); + UpdateInterface(); + } + + err = ERR_OK; + + if ( m_program == -1 ) + { + if ( action == EVENT_OBJECT_HTAKE ) + { + err = StartTaskTake(); + } + + if ( action == EVENT_OBJECT_MFRONT || + action == EVENT_OBJECT_MBACK || + action == EVENT_OBJECT_MPOWER ) + { + m_manipStyle = action; + UpdateInterface(); + } + + if ( action == EVENT_OBJECT_MTAKE ) + { + if ( m_manipStyle == EVENT_OBJECT_MFRONT ) + { + err = StartTaskManip(TMO_AUTO, TMA_FFRONT); + } + if ( m_manipStyle == EVENT_OBJECT_MBACK ) + { + err = StartTaskManip(TMO_AUTO, TMA_FBACK); + if ( err == ERR_OK ) + { + m_manipStyle = EVENT_OBJECT_MFRONT; + UpdateInterface(); + } + } + if ( m_manipStyle == EVENT_OBJECT_MPOWER ) + { + err = StartTaskManip(TMO_AUTO, TMA_POWER); + if ( err == ERR_OK ) + { + m_manipStyle = EVENT_OBJECT_MFRONT; + UpdateInterface(); + } + } + } + + if ( action == EVENT_OBJECT_BDERRICK ) + { + err = StartTaskBuild(OBJECT_DERRICK); + } + if ( action == EVENT_OBJECT_BSTATION ) + { + err = StartTaskBuild(OBJECT_STATION); + } + if ( action == EVENT_OBJECT_BFACTORY ) + { + err = StartTaskBuild(OBJECT_FACTORY); + } + if ( action == EVENT_OBJECT_BREPAIR ) + { + err = StartTaskBuild(OBJECT_REPAIR); + } + if ( action == EVENT_OBJECT_BCONVERT ) + { + err = StartTaskBuild(OBJECT_CONVERT); + } + if ( action == EVENT_OBJECT_BTOWER ) + { + err = StartTaskBuild(OBJECT_TOWER); + } + if ( action == EVENT_OBJECT_BRESEARCH ) + { + err = StartTaskBuild(OBJECT_RESEARCH); + } + if ( action == EVENT_OBJECT_BRADAR ) + { + err = StartTaskBuild(OBJECT_RADAR); + } + if ( action == EVENT_OBJECT_BENERGY ) + { + err = StartTaskBuild(OBJECT_ENERGY); + } + if ( action == EVENT_OBJECT_BLABO ) + { + err = StartTaskBuild(OBJECT_LABO); + } + if ( action == EVENT_OBJECT_BNUCLEAR ) + { + err = StartTaskBuild(OBJECT_NUCLEAR); + } + if ( action == EVENT_OBJECT_BPARA ) + { + err = StartTaskBuild(OBJECT_PARA); + } + if ( action == EVENT_OBJECT_BINFO ) + { + err = StartTaskBuild(OBJECT_INFO); + } + + if ( action == EVENT_OBJECT_GFLAT ) + { + GroundFlat(); + } + if ( action == EVENT_OBJECT_FCREATE ) + { + err = StartTaskFlag(TFL_CREATE, m_flagColor); + } + if ( action == EVENT_OBJECT_FDELETE ) + { + err = StartTaskFlag(TFL_DELETE, m_flagColor); + } + if ( action == EVENT_OBJECT_FCOLORb || + action == EVENT_OBJECT_FCOLORr || + action == EVENT_OBJECT_FCOLORg || + action == EVENT_OBJECT_FCOLORy || + action == EVENT_OBJECT_FCOLORv ) + { + ColorFlag(action-EVENT_OBJECT_FCOLORb); + } + + if ( action == EVENT_OBJECT_SEARCH ) + { + err = StartTaskSearch(); + } + + if ( action == EVENT_OBJECT_TERRAFORM ) + { + err = StartTaskTerraform(); + } + + if ( action == EVENT_OBJECT_RECOVER ) + { + err = StartTaskRecover(); + } + + if ( action == EVENT_OBJECT_BEGSHIELD ) + { + err = StartTaskShield(TSM_UP); + } + + if ( action == EVENT_OBJECT_DIMSHIELD ) + { + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD); + if ( ps != 0 ) + { + m_object->SetParam((ps->RetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); + } + } + } + + if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->RetTrainer()) + { + if ( m_camera->RetType() != CAMERA_ONBOARD ) + { + m_camera->SetType(CAMERA_ONBOARD); + } + err = StartTaskFire(0.0f); + } + if ( action == EVENT_OBJECT_TARGET && !m_object->RetTrainer() ) + { + err = StartTaskGunGoal((event.pos.y-0.50f)*1.3f, (event.pos.x-0.50f)*2.0f); + } + + if ( action == EVENT_OBJECT_FIREANT ) + { +//? err = StartTaskFireAnt(); + } + + if ( action == EVENT_OBJECT_PEN0 ) // up + { + err = StartTaskPen(FALSE, m_object->RetTraceColor()); + m_object->SetTraceDown(FALSE); + } + if ( action == EVENT_OBJECT_PEN1 ) // black + { + err = StartTaskPen(TRUE, 1); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(1); + } + if ( action == EVENT_OBJECT_PEN2 ) // yellow + { + err = StartTaskPen(TRUE, 8); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(8); + } + if ( action == EVENT_OBJECT_PEN3 ) // orange + { + err = StartTaskPen(TRUE, 7); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(7); + } + if ( action == EVENT_OBJECT_PEN4 ) // red + { + err = StartTaskPen(TRUE, 4); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(4); + } + if ( action == EVENT_OBJECT_PEN5 ) // violet + { + err = StartTaskPen(TRUE, 6); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(6); + } + if ( action == EVENT_OBJECT_PEN6 ) // blue + { + err = StartTaskPen(TRUE, 14); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(14); + } + if ( action == EVENT_OBJECT_PEN7 ) // green + { + err = StartTaskPen(TRUE, 12); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(12); + } + if ( action == EVENT_OBJECT_PEN8 ) // brown + { + err = StartTaskPen(TRUE, 10); + m_object->SetTraceDown(TRUE); + m_object->SetTraceColor(10); + } + + if ( action == EVENT_OBJECT_REC ) // registered? + { + if ( m_bTraceRecord ) + { + m_bTraceRecord = FALSE; + TraceRecordStop(); + } + else + { + m_bTraceRecord = TRUE; + TraceRecordStart(); + } + UpdateInterface(); + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + UpdateScript(pw); + } + } + if ( action == EVENT_OBJECT_STOP ) // stops? + { + if ( m_bTraceRecord ) + { + m_bTraceRecord = FALSE; + TraceRecordStop(); + } + UpdateInterface(); + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + UpdateScript(pw); + } + } + + if ( action == EVENT_OBJECT_RESET ) + { + m_main->ResetObject(); // reset all objects + UpdateInterface(); + } + +#if 0 + if ( event.param == 'T' ) + { + D3DVECTOR p1, p2; + float h; + p1 = m_object->RetPosition(0); + h = m_terrain->RetFloorLevel(p1); + p2 = p1; + p1.x -= 20.0f; + p1.z -= 20.0f; + p2.x += 20.0f; + p2.z += 20.0f; + m_terrain->Terraform(p1, p2, h+1.0f); + } + if ( event.param == 'R' ) + { + D3DVECTOR p1, p2; + float h; + p1 = m_object->RetPosition(0); + h = m_terrain->RetFloorLevel(p1); + p2 = p1; + p1.x -= 20.0f; + p1.z -= 20.0f; + p2.x += 20.0f; + p2.z += 20.0f; + m_terrain->Terraform(p1, p2, h-1.0f); + } +#endif + } + + if ( err != ERR_OK ) + { + m_displayText->DisplayError(err, m_object); + } + + return TRUE; +} + + +// The brain is changing by time. + +BOOL CBrain::EventFrame(const Event &event) +{ + m_time += event.rTime; + if ( m_bBurn ) m_burnTime += event.rTime; + + if ( m_soundChannelAlarm != -1 ) + { + m_sound->Position(m_soundChannelAlarm, m_object->RetPosition(0)); + } + + if ( m_studio != 0 ) // �urrent edition? + { + m_studio->EventProcess(event); + } + + UpdateInterface(event.rTime); + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_bActivity ) return TRUE; // expected if idle + if ( EndedTask() == ERR_CONTINUE ) return TRUE; // expected if not finished ... + + if ( m_program != -1 ) // current program? + { + if ( m_script[m_program]->Continue(event) ) + { + StopProgram(); + } + } + + if ( m_bTraceRecord ) // registration of the design in progress? + { + TraceRecordFrame(); + } + + return TRUE; +} + + +// Stops the running program. + +void CBrain::StopProgram() +{ + StopTask(); + + if ( m_object->RetType() == OBJECT_HUMAN || + m_object->RetType() == OBJECT_TECH ) return; + + if ( m_program != -1 && + m_script[m_program] != 0 ) + { + m_script[m_program]->Stop(); + } + + BlinkScript(FALSE); // stops flashing + + m_program = -1; + + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetMotorSpeedY(0.0f); + m_physics->SetMotorSpeedZ(0.0f); + + m_motion->SetAction(-1); + + UpdateInterface(); + m_main->UpdateShortcuts(); + m_object->CreateSelectParticule(); +} + +// Stops the current task. + +void CBrain::StopTask() +{ + if ( m_primaryTask != 0 ) + { + m_primaryTask->Abort(); + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } +} + + +// Introduces a virus into a program. +// Returns TRUE if it was inserted. + +BOOL CBrain::IntroduceVirus() +{ + int i, j; + + for ( i=0 ; i<50 ; i++ ) + { + j = rand()%BRAINMAXSCRIPT; + if ( m_script[j] != 0 ) + { + if ( m_script[j]->IntroduceVirus() ) // tries to introduce + { + m_bActiveVirus = TRUE; // active virus + return TRUE; + } + } + } + return FALSE; +} + +// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus) +// letters which automatically disappear after a while, +// ActiveVirus does not disappear after you edit the program +// (Even if the virus is not fixed). + + +void CBrain::SetActiveVirus(BOOL bActive) +{ + m_bActiveVirus = bActive; + + if ( !m_bActiveVirus ) // virus disabled? + { + m_object->SetVirusMode(FALSE); // chtites (??? - Programerus) letters also + } +} + +BOOL CBrain::RetActiveVirus() +{ + return m_bActiveVirus; +} + + +// Start editing a program. + +void CBrain::StartEditScript(int rank, char* name) +{ + CreateInterface(FALSE); // removes the control buttons + + if ( m_script[rank] == 0 ) + { + m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask); + } + + m_studio = new CStudio(m_iMan); + m_studio->StartEditScript(m_script[rank], name, rank); +} + +// End of editing a program. + +void CBrain::StopEditScript(BOOL bCancel) +{ + if ( !bCancel ) SetActiveVirus(FALSE); + + if ( !m_studio->StopEditScript(bCancel) ) return; + + delete m_studio; + m_studio = 0; + + CreateInterface(TRUE); // puts the control buttons +} + + + +// Move the manipulator arm. + +Error CBrain::StartTaskTake() +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskTake(); + UpdateInterface(); + return err; +} + +// Move the manipulator arm. + +Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskManip(order, arm); + UpdateInterface(); + return err; +} + +// Puts or removes a flag. + +Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskFlag(order, rank); + UpdateInterface(); + return err; +} + +// Built a building. + +Error CBrain::StartTaskBuild(ObjectType type) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskBuild(type); + UpdateInterface(); + return err; +} + +// Probe the ground. + +Error CBrain::StartTaskSearch() +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskSearch(); + UpdateInterface(); + return err; +} + +// Terraformed the ground. + +Error CBrain::StartTaskTerraform() +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskTerraform(); + UpdateInterface(); + return err; +} + +// Change pencil. + +Error CBrain::StartTaskPen(BOOL bDown, int color) +{ + Error err; + + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetMotorSpeedY(0.0f); + m_physics->SetMotorSpeedZ(0.0f); + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskPen(bDown, color); + UpdateInterface(); + return err; +} + +// Recovers a ruin. + +Error CBrain::StartTaskRecover() +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskRecover(); + UpdateInterface(); + return err; +} + +// Deploys the shield. + +Error CBrain::StartTaskShield(TaskShieldMode mode) +{ + Error err; + + if ( m_secondaryTask != 0 ) + { + delete m_secondaryTask; // stops the current task + m_secondaryTask = 0; + } + + m_secondaryTask = new CTaskManager(m_iMan, m_object); + err = m_secondaryTask->StartTaskShield(mode, 1000.0f); + UpdateInterface(); + return err; +} + +// Shoots. + +Error CBrain::StartTaskFire(float delay) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskFire(delay); + UpdateInterface(); + return err; +} + +// Shoots to the ant. + +Error CBrain::StartTaskFireAnt(D3DVECTOR impact) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskFireAnt(impact); + UpdateInterface(); + return err; +} + +// Adjusts upward. + +Error CBrain::StartTaskGunGoal(float dirV, float dirH) +{ + Error err; + + if ( m_secondaryTask != 0 ) + { + delete m_secondaryTask; // stops the current task + m_secondaryTask = 0; + } + + m_secondaryTask = new CTaskManager(m_iMan, m_object); + err = m_secondaryTask->StartTaskGunGoal(dirV, dirH); + UpdateInterface(); + return err; +} + +// Reset. + +Error CBrain::StartTaskReset(D3DVECTOR goal, D3DVECTOR angle) +{ + Error err; + + if ( m_primaryTask != 0 ) + { + delete m_primaryTask; // stops the current task + m_primaryTask = 0; + } + + m_primaryTask = new CTaskManager(m_iMan, m_object); + err = m_primaryTask->StartTaskReset(goal, angle); + UpdateInterface(); + return err; +} + +// Completes the task when the time came. + +Error CBrain::EndedTask() +{ + Error err; + + if ( m_secondaryTask != 0 ) // current task? + { + err = m_secondaryTask->IsEnded(); + if ( err != ERR_CONTINUE ) // job ended? + { + delete m_secondaryTask; + m_secondaryTask = 0; + UpdateInterface(); + } + } + + if ( m_primaryTask != 0 ) // current task? + { + err = m_primaryTask->IsEnded(); + if ( err != ERR_CONTINUE ) // job ended? + { + delete m_primaryTask; + m_primaryTask = 0; + UpdateInterface(); + } + return err; + } + return ERR_STOP; +} + + + +// Shows flat areas in the field. + +void CBrain::GroundFlat() +{ + D3DVECTOR pos, speed; + FPOINT dim; + Error err; + float level; + + if ( !m_physics->RetLand() ) + { + err = ERR_FLAG_FLY; + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) err = ERR_FLAG_WATER; + m_displayText->DisplayError(err, m_object); + return; + } + + pos = m_object->RetPosition(0); + m_terrain->GroundFlat(pos); + m_sound->Play(SOUND_GFLAT, pos); + + level = m_terrain->RetFloorLevel(pos)+2.0f; + if ( pos.y < level ) pos.y = level; // not below the soil + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 40.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGFLAT, 1.0f); +} + + +// Not below the soil. + +void CBrain::ColorFlag(int color) +{ + m_flagColor = color; + UpdateInterface(); +} + + +// Creates all the interface when the object is selected. + +BOOL CBrain::CreateInterface(BOOL bSelect) +{ + ObjectType type; + CWindow* pw; + CButton* pb; + CColor* pc; + CSlider* ps; + CTarget* pt; + CLabel* pl; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + char name[100]; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw != 0 ) + { + pw->Flush(); // destroys the window buttons + m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window + } + m_defaultEnter = EVENT_NULL; + + if ( !bSelect ) return TRUE; + + pos.x = 0.0f; + pos.y = 0.0f; + dim.x = 540.0f/640.0f; + if ( !m_main->RetShowMap() ) dim.x = 640.0f/640.0f; + dim.y = 86.0f/480.0f; + m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0); + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return FALSE; + + m_object->GetTooltipName(name); + pos.x = 0.0f; + pos.y = 64.0f/480.0f; + ddim.x = 540.0f/640.0f; + if ( !m_main->RetShowMap() ) ddim.x = 640.0f/640.0f; + ddim.y = 16.0f/480.0f; + pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name); + + dim.x = 33.0f/640.0f; + dim.y = 33.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = 33.0f/640.0f; + sy = 33.0f/480.0f; + + type = m_object->RetType(); + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || + type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM ) // vehicle? + { + ddim.x = dim.x*5.1f; + ddim.y = dim.y*2.0f; + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0.0f; + pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f); + UpdateScript(pw); + + pos.x = ox+sx*5.2f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN); + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT); + } + + if ( type == OBJECT_HUMAN || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEft || + type == OBJECT_BEE ) // driving? + { + pos.x = ox+sx*6.4f; + pos.y = oy+sy*0; + pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN); + pb->SetImmediat(TRUE); + + pos.x = ox+sx*6.4f; + pos.y = oy+sy*1; + pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP); + pb->SetImmediat(TRUE); + + if ( type != OBJECT_HUMAN || + m_object->RetOption() != 2 ) + { + pos.x = ox+sx*15.3f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE); + } + } + + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE); + DefaultEnter(pw, EVENT_OBJECT_HTAKE); + } + + if ( (type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia ) && // arm? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE); + DefaultEnter(pw, EVENT_OBJECT_MTAKE); + + pos.x = ox+sx*8.9f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK); + + pos.x = ox+sx*9.9f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER); + + pos.x = ox+sx*10.9f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT); + } + + if ( type == OBJECT_MOBILEsa && // underwater? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE); + DefaultEnter(pw, EVENT_OBJECT_MTAKE); + } + + if ( type == OBJECT_HUMAN ) // builder? + { + pos.x = 1.0f/640.0f; + pos.y = 4.0f/480.0f; + ddim.x = 212.0f/640.0f; + ddim.y = 64.0f/480.0f; + pw->CreateGroup(pos, ddim, 27, EVENT_NULL); + + ddim.x = dim.x*0.9f; + ddim.y = dim.y*0.9f; + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH); + DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH); + + pos.x = ox+sx*0.9f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY); + DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY); + + pos.x = ox+sx*1.8f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT); + DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT); + + pos.x = ox+sx*2.7f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION); + DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION); + + pos.x = ox+sx*3.6f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR); + DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR); + + pos.x = ox+sx*4.5f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR); + DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR); + + pos.x = ox+sx*5.4f; + pos.y = oy+sy*1.0f; + pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO); + DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO); + + pos.x = ox+sx*0.0f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER); + DeadInterface(pw, EVENT_OBJECT_BTOWER, + (g_build&BUILD_TOWER) && + (g_researchDone & RESEARCH_TOWER)); + + pos.x = ox+sx*0.9f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY); + DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY); + + pos.x = ox+sx*1.8f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK); + DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK); + + pos.x = ox+sx*2.7f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR); + DeadInterface(pw, EVENT_OBJECT_BNUCLEAR, + (g_build&BUILD_NUCLEAR) && + (g_researchDone & RESEARCH_ATOMIC)); + + pos.x = ox+sx*3.6f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO); + DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO); + + pos.x = ox+sx*4.5f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA); + DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA); + + pos.x = ox+sx*5.4f; + pos.y = oy+sy*0.1f; + pw->CreateButton(pos, ddim, 128+56, EVENT_OBJECT_BXXXX); + DeadInterface(pw, EVENT_OBJECT_BXXXX, FALSE); + + if ( g_build&BUILD_GFLAT ) + { + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT); + } + + if ( g_build&BUILD_FLAG ) + { + pos.x = ox+sx*10.1f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE); + + pos.x = ox+sx*11.1f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE); + + ddim.x = dim.x*0.4f; + ddim.y = dim.y*0.4f; + pos.x = ox+sx*10.1f; + pos.y = oy+sy*2.0f-ddim.y; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb); + pc->SetColor(RetColor((D3DCOLOR)0x004890ff)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr); + pc->SetColor(RetColor((D3DCOLOR)0x00ff0000)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg); + pc->SetColor(RetColor((D3DCOLOR)0x0000ce00)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy); + pc->SetColor(RetColor((D3DCOLOR)0x00ffec00)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv); + pc->SetColor(RetColor((D3DCOLOR)0x00d101fe)); + } + } + + if ( (type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis ) && // Investigator? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH); + DefaultEnter(pw, EVENT_OBJECT_SEARCH); + } + + if ( type == OBJECT_MOBILErt && // Terraformer? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM); + DefaultEnter(pw, EVENT_OBJECT_TERRAFORM); + + pos.x = ox+sx*10.2f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT); + } + + if ( type == OBJECT_MOBILErr && // recoverer? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER); + DefaultEnter(pw, EVENT_OBJECT_RECOVER); + } + + if ( type == OBJECT_MOBILErs && // shield? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD); + DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD); + + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD); + +//? pos.x = ox+sx*10.2f; +//? pos.y = oy+sy*0.5f; +//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT); + + pos.x = ox+sx*10.5f; + pos.y = oy+sy*0.0f; + ddim.x = dim.x*0.5f; + ddim.y = dim.y*2.0f; + ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD); + ps->SetState(STATE_VALUE); + ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit)); + ps->SetArrowStep(1.0f); + } + + if ( (type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILErc ) && // cannon? + !m_object->RetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE); + pb->SetImmediat(TRUE); + DefaultEnter(pw, EVENT_OBJECT_FIRE); + +//? pos.x = ox+sx*10.2f; +//? pos.y = oy+sy*0.5f; +//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT); + } + + if ( type == OBJECT_MOBILEdr && + m_object->RetManual() ) // scribbler in manual mode? + { + pos.x = ox+sx*6.9f; + pos.y = oy+sy*0.0f; + ddim.x = dim.x*2.2f; + ddim.y = dim.y*2.0f; + pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom + + pos.x = ox+sx*9.3f; + pos.y = oy+sy*0.0f; + ddim.x = dim.x*2.2f; + ddim.y = dim.y*2.0f; + pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom + + pos.x = ox+sx*9.90f; + pos.y = oy+sy*0.50f; + pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0); + + ddim.x = dim.x*0.5f; + ddim.y = dim.y*0.5f; + pos.x = ox+sx*10.15f; + pos.y = oy+sy*1.50f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black + pc->SetColor(RetColor((D3DCOLOR)0x00000000)); + pos.x = ox+sx*10.65f; + pos.y = oy+sy*1.25f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow + pc->SetColor(RetColor((D3DCOLOR)0x00ffff00)); + pos.x = ox+sx*10.90f; + pos.y = oy+sy*0.75f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange + pc->SetColor(RetColor((D3DCOLOR)0x00ff8800)); + pos.x = ox+sx*10.65f; + pos.y = oy+sy*0.25f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red + pc->SetColor(RetColor((D3DCOLOR)0x00ff0000)); + pos.x = ox+sx*10.15f; + pos.y = oy+sy*0.00f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet + pc->SetColor(RetColor((D3DCOLOR)0x00ff00ff)); + pos.x = ox+sx*9.65f; + pos.y = oy+sy*0.25f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue + pc->SetColor(RetColor((D3DCOLOR)0x000066ff)); + pos.x = ox+sx*9.40f; + pos.y = oy+sy*0.75f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green + pc->SetColor(RetColor((D3DCOLOR)0x0000cc00)); + pos.x = ox+sx*9.65f; + pos.y = oy+sy*1.25f; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown + pc->SetColor(RetColor((D3DCOLOR)0x00884400)); + + pos.x = ox+sx*6.9f; + pos.y = oy+sy*1.2f; + ddim.x = dim.x*2.2f; + ddim.y = dim.y*0.4f; + GetResource(RES_TEXT, RT_INTERFACE_REC, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name); + pl->SetFontSize(9.0f); + + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.3f; + pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC); + pos.x = ox+sx*8.0f; + pos.y = oy+sy*0.3f; + pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP); + } + + if ( m_object->RetToy() ) + { + pos.x = ox+sx*12.1f; + pos.y = oy+sy*-0.1f; + ddim.x = dim.x*1.2f; + ddim.y = dim.y*2.1f; + pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom + + pos.x = ox+sx*12.2f; + pos.y = oy+sy*1; + pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom + + pos.x = ox+sx*12.2f; + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP); + } + else + { + pos.x = ox+sx*12.3f; + pos.y = oy+sy*-0.1f; + ddim.x = dim.x*1.0f; + ddim.y = dim.y*2.1f; + pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom + + pos.x = ox+sx*12.3f; + pos.y = oy+sy*1; + pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom + + pos.x = ox+sx*12.4f; + pos.y = oy+sy*0.5f; + ddim.x = dim.x*0.8f; + ddim.y = dim.y*0.5f; + pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP); + pos.y = oy+sy*0.0f; + pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP); + } + + if ( type != OBJECT_HUMAN && + type != OBJECT_TECH && + !m_object->RetCameraLock() ) + { +//? if ( m_main->RetShowMap() ) + if ( TRUE ) + { + pos.x = ox+sx*13.4f; + pos.y = oy+sy*1; + pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA); + } + else + { + ddim.x = dim.x*0.66f; + ddim.y = dim.y*0.66f; + pos.x = ox+sx*(17.0f+0.66f); + pos.y = oy+sy*0.66f; + pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA); + } + } + + if ( m_object->RetToy() && !m_object->RetManual() ) + { +#if 0 + ddim.x = dim.x*0.66f; + ddim.y = dim.y*0.66f; + pos.x = ox+sx*10.0f; + pos.y = oy+sy*0.66f; + pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft); + pb->SetImmediat(TRUE); + pos.x = ox+sx*(10.0f+0.66f*2.0f); + pos.y = oy+sy*0.66f; + pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright); + pb->SetImmediat(TRUE); + pos.x = ox+sx*(10.0f+0.66f); + pos.y = oy+sy*(0.66f*2.0f); + pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear); + pb->SetImmediat(TRUE); + pos.x = ox+sx*(10.0f+0.66f); + pos.y = oy+sy*0.0f; + pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway); + pb->SetImmediat(TRUE); +#else + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0; + pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft); + pb->SetImmediat(TRUE); + pos.x = ox+sx*11.0f; + pos.y = oy+sy*0; + pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright); + pb->SetImmediat(TRUE); + pos.x = ox+sx*10.0f; + pos.y = oy+sy*1; + pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear); + pb->SetImmediat(TRUE); + pos.x = ox+sx*10.0f; + pos.y = oy+sy*0; + pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway); + pb->SetImmediat(TRUE); +#endif + } + + pos.x = ox+sx*13.4f; + pos.y = oy+sy*0; +#if _TEEN + pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET); +#else + if ( m_object->RetTrainer() ) // Training? + { + pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET); + } + else + { + pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT); + } +#endif + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit ) // vehicle? + { + pos.x = ox+sx*14.5f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY); + } + + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit ) // vehicle? + { + pos.x = ox+sx*14.9f; + pos.y = oy+sy*0; + ddim.x = 14.0f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD); + } + +#if 0 + if ( FALSE ) + { + pos.x = 505.0f/640.0f; + pos.y = 3.0f/480.0f; + ddim.x = 33.0f/640.0f; + ddim.y = 33.0f/480.0f; + pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS); + + pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS); + if ( pc != 0 ) + { + pc->SetState(STATE_VISIBLE, m_main->RetShowMap()); + } + } +#endif + + if ( type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILErc ) // cannon? + { + ddim.x = 64.0f/640.0f; + ddim.y = 64.0f/480.0f; + pos.x = 0.5f-ddim.x/2.0f; + pos.y = 0.5f-ddim.y/2.0f; + pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR); + + pos.x = 20.0f/640.0f; + pos.y = 100.0f/480.0f; + ddim.x = 600.0f/640.0f; + ddim.y = 340.0f/480.0f; + pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET); + pt->ClearState(STATE_GLINT); + } + + ddim.x = 64.0f/640.0f; + ddim.y = 64.0f/480.0f; + pos.x = 30.0f/640.0f; + pos.y = 430.0f/480.0f-ddim.y; + pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul); + + ddim.x = 64.0f/640.0f; + ddim.y = 64.0f/480.0f; + pos.x = 610.0f/640.0f-ddim.x; + pos.y = 430.0f/480.0f-ddim.y; + pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur); + + ddim.x = 64.0f/640.0f; + ddim.y = 64.0f/480.0f; + pos.x = 30.0f/640.0f; + pos.y = 110.0f/480.0f; + pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl); + + ddim.x = 64.0f/640.0f; + ddim.y = 64.0f/480.0f; + pos.x = 610.0f/640.0f-ddim.x; + pos.y = 110.0f/480.0f; + pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr); + + UpdateInterface(); + m_lastUpdateTime = 0.0f; + UpdateInterface(0.0f); + + return TRUE; +} + +// Updates the state of all buttons on the interface, +// following the time that elapses ... + +void CBrain::UpdateInterface(float rTime) +{ + CWindow* pw; +#if _TEEN + CButton* pb; +#endif + CGauge* pg; + CCompass* pc; + CGroup* pgr; + CTarget* ptg; + CObject* power; + D3DVECTOR pos, hPos; + FPOINT ppos; + float energy, limit, angle, range; + int icon; + BOOL bOnBoard; + + m_lastAlarmTime += rTime; + if ( m_time < m_lastUpdateTime+0.1f ) return; + m_lastUpdateTime = m_time; + + if ( !m_object->RetSelect() ) + { + if ( m_soundChannelAlarm != -1 ) + { + m_sound->FlushEnvelope(m_soundChannelAlarm); + m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP); + m_soundChannelAlarm = -1; + } + return; + } + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY); + if ( pg != 0 ) + { + power = m_object->RetPower(); + if ( power == 0 ) + { + energy = 0.0f; + } + else + { + energy = power->RetEnergy(); + limit = energy*power->RetCapacity(); + } + icon = 0; // red/green + + if ( limit < 0.2f && energy != 0.0f ) // low but not zero? + { + if ( m_lastAlarmTime >= 0.8f ) // blinks? + { + energy = 1.0f; + icon = 1; // brun + } + if ( m_lastAlarmTime >= 1.0f ) + { + m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip + m_lastAlarmTime = 0.0f; + } + } + pg->SetLevel(energy); + pg->SetIcon(icon); + } + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD); + if ( pg != 0 ) + { + pg->SetLevel(m_object->RetShield()); + } + + pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRANGE); + if ( pg != 0 ) + { + icon = 2; // blue/red + range = m_physics->RetReactorRange(); + + if ( range < 0.2f && range != 0.0f && !m_physics->RetLand() ) + { + if ( Mod(m_time, 0.5f) >= 0.2f ) // blinks? + { + range = 1.0f; + icon = 1; // yellow + } + if ( m_soundChannelAlarm == -1 ) + { + m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->RetPosition(0), 0.0f, 0.1f, TRUE); + m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP); + } + } + else + { + if ( m_soundChannelAlarm != -1 ) + { + m_sound->FlushEnvelope(m_soundChannelAlarm); + m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP); + m_soundChannelAlarm = -1; + } + } + + pg->SetLevel(1.0f-range); + pg->SetIcon(icon); + } + + pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS); + if ( pc != 0 ) + { + angle = -(m_object->RetAngleY(0)+PI/2.0f); + pc->SetDirection(angle); + + pc->SetState(STATE_VISIBLE, m_main->RetShowMap()); + } + +#if _TEEN + pb = (CButton*)pw->SearchControl(EVENT_OBJECT_REC); + if ( pb != 0 ) + { + if ( m_bTraceRecord && Mod(m_time, 0.4f) >= 0.2f ) + { + pb->SetState(STATE_CHECK); + } + else + { + pb->ClearState(STATE_CHECK); + } + } +#endif + + bOnBoard = m_camera->RetType() == CAMERA_ONBOARD; + + pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CROSSHAIR); + if ( pgr != 0 ) + { + if ( bOnBoard ) + { +#if 0 + angle = m_object->RetGunGoalV(); + if ( m_object->RetType() != OBJECT_MOBILErc ) + { + angle += 10.0f*PI/360.0f; + } + ppos.x = 0.5f-(64.0f/640.0f)/2.0f; + ppos.y = 0.5f-(64.0f/480.0f)/2.0f; + ppos.y += sinf(angle)*0.6f; + pgr->SetPos(ppos); +#else + ppos.x = 0.50f-(64.0f/640.0f)/2.0f; + ppos.y = 0.50f-(64.0f/480.0f)/2.0f; + ppos.x += m_object->RetGunGoalH()/2.0f; + ppos.y += m_object->RetGunGoalV()/1.3f; + pgr->SetPos(ppos); +#endif + pgr->SetState(STATE_VISIBLE, !m_main->RetFriendAim()); + } + else + { + pgr->ClearState(STATE_VISIBLE); + } + } + + ptg = (CTarget*)pw->SearchControl(EVENT_OBJECT_TARGET); + if ( ptg != 0 ) + { + if ( bOnBoard ) + { + ptg->SetState(STATE_VISIBLE); + } + else + { + ptg->ClearState(STATE_VISIBLE); + } + } + + pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERul); + if ( pgr != 0 ) + { + pgr->SetState(STATE_VISIBLE, bOnBoard); + } + + pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERur); + if ( pgr != 0 ) + { + pgr->SetState(STATE_VISIBLE, bOnBoard); + } + + pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdl); + if ( pgr != 0 ) + { + pgr->SetState(STATE_VISIBLE, bOnBoard); + } + + pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdr); + if ( pgr != 0 ) + { + pgr->SetState(STATE_VISIBLE, bOnBoard); + } +} + +// Updates the status of all interface buttons. + +void CBrain::UpdateInterface() +{ + ObjectType type; + CWindow* pw; + CButton* pb; + CSlider* ps; +#if _TEEN + CColor* pc; + int color; +#endif + BOOL bEnable, bFly, bRun; + char title[100]; + + if ( !m_object->RetSelect() ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + type = m_object->RetType(); + + bEnable = ( m_secondaryTask == 0 && m_program == -1 ); + + bEnable = ( m_primaryTask == 0 && m_program == -1 ); + + EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord)); + EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord); + EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable); + EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable); + EnableInterface(pw, EVENT_OBJECT_UP, bEnable); + EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable); + EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable); + EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable); + EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable); + EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable); + EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable); + EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable); + EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable); + EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable); + EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable); + EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable); + EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable); + EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable); + EnableInterface(pw, EVENT_OBJECT_RESET, bEnable); +#if _TEEN + EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable); + EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable); + EnableInterface(pw, EVENT_OBJECT_REC, bEnable); + EnableInterface(pw, EVENT_OBJECT_STOP, bEnable); +#endif + + if ( type == OBJECT_HUMAN ) // builder? + { + EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable); + EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable); + EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable); + EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable); + EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable); + EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable); + EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable); + EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable); + EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable); + EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable); + EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable); + EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable); + EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable); + EnableInterface(pw, EVENT_OBJECT_BXXXX, bEnable); + } + + pb = (CButton*)pw->SearchControl(EVENT_OBJECT_GFLAT); + if ( pb != 0 ) + { + pb->SetState(STATE_VISIBLE, m_engine->RetGroundSpot()); + } + + if ( type == OBJECT_HUMAN || // builder? + type == OBJECT_TECH ) + { + CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0); + CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1); + CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2); + CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3); + CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4); + } + + if ( type == OBJECT_MOBILErs ) // shield? + { + if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_program == -1 ) + { + EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0)); + EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0)); + DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0)); + DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0)); + } + else + { + EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, FALSE); + EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, FALSE); + DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, FALSE); + DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, FALSE); + } + + ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD); + if ( ps != 0 ) + { + ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->RetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); + } + } + + bFly = bEnable; + if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) ) + { + if ( m_object->RetFret() != 0 ) bFly = FALSE; // if holder -> not fly + } + EnableInterface(pw, EVENT_OBJECT_GASUP, bFly); + EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly); + if ( m_object->RetTrainer() ) // Training? + { + DeadInterface(pw, EVENT_OBJECT_GASUP, FALSE); + DeadInterface(pw, EVENT_OBJECT_GASDOWN, FALSE); + } + else + { + DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY); + DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY); + } + + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || + type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM ) // vehicle? + { + bRun = FALSE; + if ( m_script[m_selScript] != 0 ) + { + m_script[m_selScript]->GetTitle(title); + if ( title[0] != 0 ) + { + bRun = TRUE; + } + } + if ( !bEnable && m_program == -1 ) bRun = FALSE; + if ( m_bTraceRecord ) bRun = FALSE; + EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun); + + pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGRUN); + if ( pb != 0 ) + { + pb->SetIcon(m_program==-1?21:8); // run/stop + } + +//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT); +//? if ( pb != 0 ) +//? { +//? pb->SetIcon(m_program==-1?22:40); // edit/debug +//? } + + BlinkScript(m_program != -1); // blinks if script execution + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia ) // arm? + { + CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER); + CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK); + CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT); + } + +#if _TEEN + if ( m_object->RetTraceDown() ) + { + pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0); + if ( pb != 0 ) + { + pb->ClearState(STATE_CHECK); + } + + color = m_object->RetTraceColor(); + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==1); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==8); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==7); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==4); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==6); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==14); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==12); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8); + if ( pc != 0 ) + { + pc->SetState(STATE_CHECK, color==10); + } + } + else + { + pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0); + if ( pb != 0 ) + { + pb->SetState(STATE_CHECK); + } + + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8); + if ( pc != 0 ) + { + pc->ClearState(STATE_CHECK); + } + } +#endif +} + +// Updates the list of programs. + +void CBrain::UpdateScript(CWindow *pw) +{ + CList* pl; + char name[100]; + char title[100]; + int i; + BOOL bSoluce; + + pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST); + if ( pl == 0 ) return; + +#if _SCHOOL + bSoluce = m_main->RetSoluce4(); +#else + bSoluce = TRUE; +#endif + + for ( i=0 ; iGetTitle(title); + if ( !bSoluce && i == 3 ) + { + title[0] = 0; + } + if ( title[0] != 0 ) + { + sprintf(name, "%d: %s", i+1, title); + } + } + + pl->SetName(i, name); + } + + if ( !bSoluce ) + { + pl->SetEnable(3, FALSE); + } + + pl->SetSelect(m_selScript); + pl->ShowSelect(TRUE); +} + +// Returns the rank of selected script. + +int CBrain::RetSelScript() +{ + CWindow* pw; + CList* pl; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return -1; + + pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST); + if ( pl == 0 ) return -1; + + return pl->RetSelect(); +} + +// Blinks the running program. + +void CBrain::BlinkScript(BOOL bEnable) +{ + CWindow* pw; + CList* pl; + + if ( !m_object->RetSelect() ) return; // robot not selected? + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0); + if ( pw == 0 ) return; + + pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST); + if ( pl == 0 ) return; + + pl->SetBlink(bEnable); +} + +// Check the status of a button interface. + +void CBrain::CheckInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_CHECK, bState); +} + +// Changes the state of a button interface. + +void CBrain::EnableInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_ENABLE, bState); +} + +// Changes the state of a button on the interface. + +void CBrain::DeadInterface(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + control->SetState(STATE_DEAD, !bState); +} + +// Change the default input state of a button interface. + +void CBrain::DefaultEnter(CWindow *pw, EventMsg event, BOOL bState) +{ + CControl* control; + + control = pw->SearchControl(event); + if ( control == 0 ) return; + + if ( bState ) + { + control->SetState(STATE_DEFAULT); + m_defaultEnter = event; + } + else + { + control->ClearState(STATE_DEFAULT); + } +} + + +// Indicates whether the object is busy with a task. + +BOOL CBrain::IsBusy() +{ + return (m_primaryTask != 0); +} + +// Management of the activity of an object. + +void CBrain::SetActivity(BOOL bMode) +{ + m_bActivity = bMode; +} + +BOOL CBrain::RetActivity() +{ + return m_bActivity; +} + +// Indicates whether a program is running. + +BOOL CBrain::IsProgram() +{ + return ( m_program != -1 ); +} + +// Indicates whether a program exists. + +BOOL CBrain::ProgramExist(int rank) +{ + return ( m_script[rank] != 0 ); +} + +// Starts a program. + +void CBrain::RunProgram(int rank) +{ + if ( rank < 0 ) return; + + if ( m_script[rank] != 0 && + m_script[rank]->Run() ) + { + m_program = rank; // start new program + BlinkScript(TRUE); // blink + m_object->CreateSelectParticule(); + m_main->UpdateShortcuts(); + } +} + +// Returns the first free program. + +int CBrain::FreeProgram() +{ + int i; + + for ( i=0 ; iCompare(m_script[rank]) ) // the same already? + { + delete m_script[rank]; + m_script[rank] = 0; + return FALSE; + } + } + + return TRUE; +} + +// Load a script with a text file. + +BOOL CBrain::ReadProgram(int rank, char* filename) +{ + if ( m_script[rank] == 0 ) + { + m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask); + } + + if ( m_script[rank]->ReadScript(filename) ) return TRUE; + + delete m_script[rank]; + m_script[rank] = 0; + + return FALSE; +} + +// Indicates whether a program is compiled correctly. + +BOOL CBrain::RetCompile(int rank) +{ + if ( m_script[rank] == 0 ) return FALSE; + return m_script[rank]->RetCompile(); +} + +// Saves a script in a text file. + +BOOL CBrain::WriteProgram(int rank, char* filename) +{ + if ( m_script[rank] == 0 ) + { + m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask); + } + + if ( m_script[rank]->WriteScript(filename) ) return TRUE; + + delete m_script[rank]; + m_script[rank] = 0; + + return FALSE; +} + + +// Load a stack of script implementation from a file. + +BOOL CBrain::ReadStack(FILE *file) +{ + short op; + + fRead(&op, sizeof(short), 1, file); + if ( op == 1 ) // run ? + { + fRead(&op, sizeof(short), 1, file); // program rank + if ( op >= 0 && op < BRAINMAXSCRIPT ) + { + m_program = op; // program restarts + m_selScript = op; + BlinkScript(TRUE); // blink + + if ( m_script[op] == 0 ) + { + m_script[op] = new CScript(m_iMan, m_object, &m_secondaryTask); + } + if ( !m_script[op]->ReadStack(file) ) return FALSE; + } + } + + return TRUE; +} + +// ave the script implementation stack of a file. + +BOOL CBrain::WriteStack(FILE *file) +{ + short op; + + if ( m_program != -1 && // current program? + m_script[m_program]->IsRunning() ) + { + op = 1; // run + fWrite(&op, sizeof(short), 1, file); + + op = m_program; + fWrite(&op, sizeof(short), 1, file); + + return m_script[m_program]->WriteStack(file); + } + + op = 0; // stop + fWrite(&op, sizeof(short), 1, file); + return TRUE; +} + + + +// Start of registration of the design. + +void CBrain::TraceRecordStart() +{ + m_traceOper = TO_STOP; + + m_tracePos = m_object->RetPosition(0); + m_traceAngle = m_object->RetAngleY(0); + + if ( m_object->RetTraceDown() ) // pencil down? + { + m_traceColor = m_object->RetTraceColor(); + } + else // pen up? + { + m_traceColor = -1; + } + + delete m_traceRecordBuffer; + m_traceRecordBuffer = (TraceRecord*)malloc(sizeof(TraceRecord)*MAXTRACERECORD); + m_traceRecordIndex = 0; +} + +// Saving the current drawing. + +void CBrain::TraceRecordFrame() +{ + TraceOper oper = TO_STOP; + D3DVECTOR pos; + float angle, len, speed; + int color; + + speed = m_physics->RetLinMotionX(MO_REASPEED); + if ( speed > 0.0f ) oper = TO_ADVANCE; + if ( speed < 0.0f ) oper = TO_RECEDE; + + speed = m_physics->RetCirMotionY(MO_REASPEED); + if ( speed != 0.0f ) oper = TO_TURN; + + if ( m_object->RetTraceDown() ) // pencil down? + { + color = m_object->RetTraceColor(); + } + else // pen up? + { + color = -1; + } + + if ( oper != m_traceOper || + color != m_traceColor ) + { + if ( m_traceOper == TO_ADVANCE || + m_traceOper == TO_RECEDE ) + { + pos = m_object->RetPosition(0); + len = Length2d(pos, m_tracePos); + TraceRecordOper(m_traceOper, len); + } + if ( m_traceOper == TO_TURN ) + { + angle = m_object->RetAngleY(0)-m_traceAngle; + TraceRecordOper(m_traceOper, angle); + } + + if ( color != m_traceColor ) + { + TraceRecordOper(TO_PEN, (float)color); + } + + m_traceOper = oper; + m_tracePos = m_object->RetPosition(0); + m_traceAngle = m_object->RetAngleY(0); + m_traceColor = color; + } +} + +// End of the registration of the design. Program generates the CBOT. + +void CBrain::TraceRecordStop() +{ + TraceOper lastOper, curOper; + float lastParam, curParam; + int max, i; + char* buffer; + + if ( m_traceRecordBuffer == 0 ) return; + + max = 10000; + buffer = (char*)malloc(max); + *buffer = 0; + strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1); + + lastOper = TO_STOP; + lastParam = 0.0f; + for ( i=0 ; iSendScript(buffer); + delete buffer; +} + +// Saves an instruction CBOT. + +BOOL CBrain::TraceRecordOper(TraceOper oper, float param) +{ + int i; + + i = m_traceRecordIndex; + if ( i >= MAXTRACERECORD ) return FALSE; + + m_traceRecordBuffer[i].oper = oper; + m_traceRecordBuffer[i].param = param; + + m_traceRecordIndex = i+1; + return TRUE; +} + +// Generates an instruction CBOT. + +BOOL CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param) +{ + char line[100]; + int color; + + if ( oper == TO_ADVANCE ) + { + param /= g_unit; + sprintf(line, "\tmove(%.1f);\n", param); + strncat(buffer, line, max-1); + } + + if ( oper == TO_RECEDE ) + { + param /= g_unit; + sprintf(line, "\tmove(-%.1f);\n", param); + strncat(buffer, line, max-1); + } + + if ( oper == TO_TURN ) + { + param = -param*180.0f/PI; + sprintf(line, "\tturn(%d);\n", (int)param); +//? sprintf(line, "\tturn(%.1f);\n", param); + strncat(buffer, line, max-1); + } + + if ( oper == TO_PEN ) + { + color = (int)param; + if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1); + if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1); + if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1); + if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1); + if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1); + if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1); + if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1); + if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1); + if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1); + } + + return TRUE; +} + diff --git a/src/object/brain.h b/src/object/brain.h new file mode 100644 index 0000000..988a3cc --- /dev/null +++ b/src/object/brain.h @@ -0,0 +1,220 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// brain.h + +#ifndef _BRAIN_H_ +#define _BRAIN_H_ + + +#include "misc.h" +#include "event.h" +#include "object.h" +#include "taskmanip.h" +#include "taskflag.h" +#include "taskshield.h" + + +class CInstanceManager; +class CD3DEngine; +class CTerrain; +class CWater; +class CCamera; +class CObject; +class CPhysics; +class CMotion; +class CTaskManager; +class CInterface; +class CWindow; +class CDisplayText; +class CScript; +class CRobotMain; +class CStudio; +class CSound; +class CParticule; + + +#define BRAINMAXSCRIPT 10 + + + +enum TraceOper +{ + TO_STOP = 0, // stop + TO_ADVANCE = 1, // advance + TO_RECEDE = 2, // back + TO_TURN = 3, // rotate + TO_PEN = 4, // color change +}; + +typedef struct +{ + TraceOper oper; + float param; +} +TraceRecord; + + + +class CBrain +{ +public: + CBrain(CInstanceManager* iMan, CObject* object); + ~CBrain(); + + void DeleteObject(BOOL bAll=FALSE); + + void SetPhysics(CPhysics* physics); + void SetMotion(CMotion* motion); + + BOOL EventProcess(const Event &event); + BOOL CreateInterface(BOOL bSelect); + + BOOL Write(char *line); + BOOL Read(char *line); + + BOOL IsBusy(); + void SetActivity(BOOL bMode); + BOOL RetActivity(); + BOOL IsProgram(); + BOOL ProgramExist(int rank); + void RunProgram(int rank); + int FreeProgram(); + int RetProgram(); + void StopProgram(); + void StopTask(); + + BOOL IntroduceVirus(); + void SetActiveVirus(BOOL bActive); + BOOL RetActiveVirus(); + + void SetScriptRun(int rank); + int RetScriptRun(); + void SetScriptName(int rank, char *name); + char* RetScriptName(int rank); + void SetSoluceName(char *name); + char* RetSoluceName(); + + BOOL ReadSoluce(char* filename); + BOOL ReadProgram(int rank, char* filename); + BOOL RetCompile(int rank); + BOOL WriteProgram(int rank, char* filename); + BOOL ReadStack(FILE *file); + BOOL WriteStack(FILE *file); + + Error StartTaskTake(); + Error StartTaskManip(TaskManipOrder order, TaskManipArm arm); + Error StartTaskFlag(TaskFlagOrder order, int rank); + Error StartTaskBuild(ObjectType type); + Error StartTaskSearch(); + Error StartTaskTerraform(); + Error StartTaskPen(BOOL bDown, int color); + Error StartTaskRecover(); + Error StartTaskShield(TaskShieldMode mode); + Error StartTaskFire(float delay); + Error StartTaskFireAnt(D3DVECTOR impact); + Error StartTaskGunGoal(float dirV, float dirH); + Error StartTaskReset(D3DVECTOR goal, D3DVECTOR angle); + + void UpdateInterface(float rTime); + void UpdateInterface(); + +protected: + BOOL EventFrame(const Event &event); + + void StartEditScript(int rank, char* name); + void StopEditScript(BOOL bCancel); + + Error EndedTask(); + + void GroundFlat(); + void ColorFlag(int color); + + void UpdateScript(CWindow *pw); + int RetSelScript(); + void BlinkScript(BOOL bEnable); + + void CheckInterface(CWindow *pw, EventMsg event, BOOL bState); + void EnableInterface(CWindow *pw, EventMsg event, BOOL bState); + void DeadInterface(CWindow *pw, EventMsg event, BOOL bState); + void DefaultEnter(CWindow *pw, EventMsg event, BOOL bState=TRUE); + + void TraceRecordStart(); + void TraceRecordFrame(); + void TraceRecordStop(); + BOOL TraceRecordOper(TraceOper oper, float param); + BOOL TraceRecordPut(char *buffer, int max, TraceOper oper, float param); + +protected: + CInstanceManager* m_iMan; + CD3DEngine* m_engine; + CTerrain* m_terrain; + CWater* m_water; + CCamera* m_camera; + CObject* m_object; + CPhysics* m_physics; + CMotion* m_motion; + CInterface* m_interface; + CDisplayText* m_displayText; + CRobotMain* m_main; + CStudio* m_studio; + CSound* m_sound; + CParticule* m_particule; + CTaskManager* m_primaryTask; + CTaskManager* m_secondaryTask; + + CScript* m_script[BRAINMAXSCRIPT]; + int m_selScript; // rank of the selected script + int m_program; // rank of the executed program / ​​-1 + BOOL m_bActivity; + BOOL m_bBurn; + BOOL m_bActiveVirus; + + int m_scriptRun; + char m_scriptName[BRAINMAXSCRIPT][50]; + char m_soluceName[50]; + + EventMsg m_buttonAxe; + EventMsg m_manipStyle; + EventMsg m_defaultEnter; + EventMsg m_interfaceEvent[100]; + + CObject* m_antTarget; + CObject* m_beeBullet; + float m_beeBulletSpeed; + D3DVECTOR m_startPos; + float m_time; + float m_burnTime; + float m_lastUpdateTime; + float m_lastHumanTime; + float m_lastSpiderTime; + float m_lastWormTime; + float m_lastBulletTime; + float m_lastAlarmTime; + int m_soundChannelAlarm; + int m_flagColor; + + BOOL m_bTraceRecord; + TraceOper m_traceOper; + D3DVECTOR m_tracePos; + float m_traceAngle; + int m_traceColor; + int m_traceRecordIndex; + TraceRecord* m_traceRecordBuffer; +}; + + +#endif //_BRAIN_H_ diff --git a/src/object/motion/motion.cpp b/src/object/motion/motion.cpp new file mode 100644 index 0000000..642108b --- /dev/null +++ b/src/object/motion/motion.cpp @@ -0,0 +1,257 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motion.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "robotmain.h" +#include "sound.h" +#include "cmdtoken.h" +#include "motion.h" + + + + +// Object's constructor. + +CMotion::CMotion(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_MOTION, this, 100); + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + + m_object = object; + m_physics = 0; + m_brain = 0; + + m_actionType = -1; + m_actionTime = 0.0f; + m_progress = 0.0f; + + m_linVibration = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_cirVibration = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_inclinaison = D3DVECTOR(0.0f, 0.0f, 0.0f); +} + +// Object's destructor. + +CMotion::~CMotion() +{ + m_iMan->DeleteInstance(CLASS_MOTION, this); +} + +// Deletes the object. + +void CMotion::DeleteObject(BOOL bAll) +{ +} + + +void CMotion::SetPhysics(CPhysics* physics) +{ + m_physics = physics; +} + +void CMotion::SetBrain(CBrain* brain) +{ + m_brain = brain; +} + + +// Creates. + +BOOL CMotion::Create(D3DVECTOR pos, float angle, ObjectType type, float power) +{ + return TRUE; +} + +// Management of an event. + +BOOL CMotion::EventProcess(const Event &event) +{ + D3DVECTOR pos, dir; + float time; + + if ( m_object->RetType() != OBJECT_TOTO && + m_engine->RetPause() ) return TRUE; + + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_actionTime; + if ( m_progress > 1.0f ) m_progress = 1.0f; // (*) + + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel(m_object) ) // underwater? + { + time = event.rTime*3.0f; // everything is slower + } + else + { + time = event.rTime*10.0f; + } + + dir = m_object->RetLinVibration(); + dir.x = Smooth(dir.x, m_linVibration.x, time); + dir.y = Smooth(dir.y, m_linVibration.y, time); + dir.z = Smooth(dir.z, m_linVibration.z, time); + m_object->SetLinVibration(dir); + + dir = m_object->RetCirVibration(); + dir.x = Smooth(dir.x, m_cirVibration.x, time); + dir.y = Smooth(dir.y, m_cirVibration.y, time); + dir.z = Smooth(dir.z, m_cirVibration.z, time); + m_object->SetCirVibration(dir); + + dir = m_object->RetInclinaison(); + dir.x = Smooth(dir.x, m_inclinaison.x, time); + dir.y = Smooth(dir.y, m_inclinaison.y, time); + dir.z = Smooth(dir.z, m_inclinaison.z, time); + m_object->SetInclinaison(dir); + + return TRUE; +} + +// (*) Avoids the bug of ants returned by the thumper and +// whose abdomen grown to infinity! + + +// Start an action. + +Error CMotion::SetAction(int action, float time) +{ + m_actionType = action; + m_actionTime = 1.0f/time; + m_progress = 0.0f; + return ERR_OK; +} + +// Returns the current action. + +int CMotion::RetAction() +{ + return m_actionType; +} + + +// Specifies a special parameter. + +BOOL CMotion::SetParam(int rank, float value) +{ + return FALSE; +} + +float CMotion::RetParam(int rank) +{ + return 0.0f; +} + + +// Saves all parameters of the object. + +BOOL CMotion::Write(char *line) +{ + char name[100]; + + if ( m_actionType == -1 ) return FALSE; + + sprintf(name, " mType=%d", m_actionType); + strcat(line, name); + + sprintf(name, " mTime=%.2f", m_actionTime); + strcat(line, name); + + sprintf(name, " mProgress=%.2f", m_progress); + strcat(line, name); + + return FALSE; +} + +// Restores all parameters of the object. + +BOOL CMotion::Read(char *line) +{ + m_actionType = OpInt(line, "mType", -1); + m_actionTime = OpFloat(line, "mTime", 0.0f); + m_progress = OpFloat(line, "mProgress", 0.0f); + + return FALSE; +} + + +// Gives the linear vibration. + +void CMotion::SetLinVibration(D3DVECTOR dir) +{ + m_linVibration = dir; +} + +D3DVECTOR CMotion::RetLinVibration() +{ + return m_linVibration; +} + +// Gives the circular vibration. + +void CMotion::SetCirVibration(D3DVECTOR dir) +{ + m_cirVibration = dir; +} + +D3DVECTOR CMotion::RetCirVibration() +{ + return m_cirVibration; +} + +// Gives the tilt. + +void CMotion::SetInclinaison(D3DVECTOR dir) +{ + m_inclinaison = dir; +} + +D3DVECTOR CMotion::RetInclinaison() +{ + return m_inclinaison; +} + diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h new file mode 100644 index 0000000..5aa0afb --- /dev/null +++ b/src/object/motion/motion.h @@ -0,0 +1,94 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motion.h + +#ifndef _MOTION_H_ +#define _MOTION_H_ + + +#include "d3dengine.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CWater; +class CCamera; +class CBrain; +class CPhysics; +class CObject; +class CRobotMain; +class CSound; + + +class CMotion +{ +public: + CMotion(CInstanceManager* iMan, CObject* object); + virtual ~CMotion(); + + void SetPhysics(CPhysics* physics); + void SetBrain(CBrain* brain); + + virtual void DeleteObject(BOOL bAll=FALSE); + virtual BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + virtual BOOL EventProcess(const Event &event); + virtual Error SetAction(int action, float time=0.2f); + virtual int RetAction(); + + virtual BOOL SetParam(int rank, float value); + virtual float RetParam(int rank); + + virtual BOOL Write(char *line); + virtual BOOL Read(char *line); + + virtual void SetLinVibration(D3DVECTOR dir); + virtual D3DVECTOR RetLinVibration(); + virtual void SetCirVibration(D3DVECTOR dir); + virtual D3DVECTOR RetCirVibration(); + virtual void SetInclinaison(D3DVECTOR dir); + virtual D3DVECTOR RetInclinaison(); + +protected: + +protected: + CInstanceManager* m_iMan; + CD3DEngine* m_engine; + CLight* m_light; + CParticule* m_particule; + CTerrain* m_terrain; + CWater* m_water; + CCamera* m_camera; + CObject* m_object; + CBrain* m_brain; + CPhysics* m_physics; + CRobotMain* m_main; + CSound* m_sound; + + int m_actionType; + float m_actionTime; + float m_progress; + + D3DVECTOR m_linVibration; // linear vibration + D3DVECTOR m_cirVibration; // circular vibration + D3DVECTOR m_inclinaison; // tilt +}; + + +#endif //_MOTION_H_ diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp new file mode 100644 index 0000000..3790f7e --- /dev/null +++ b/src/object/motion/motionant.cpp @@ -0,0 +1,901 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionant.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionant.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeMarch = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLastAction = -1; + m_bArmStop = FALSE; + m_lastParticule = 0.0f; +} + +// Object's destructor. + +CMotionAnt::~CMotionAnt() +{ +} + + +// Removes an object. + +void CMotionAnt::DeleteObject(BOOL bAll) +{ +} + + +// Creates a vehicle poses some rolling on the floor. + +BOOL CMotionAnt::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 3+18 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + + pModFile->ReadModel("objects\\ant1.mod"); + pModFile->CreateEngineObject(rank); + + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have necessarily a collision + //with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(-0.5f, 1.0f, 0.0f), 4.0f); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\ant2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(2.0f, 0.0f, 0.0f)); + + // Creates the tail. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\ant3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(-1.0f, 0.0f, 0.0f)); + + // Creates a right-back thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(-0.4f, -0.1f, -0.3f)); + + // Creates a right-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 3); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates a right-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates two middle-right thighs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.1f, -0.1f, -0.4f)); + + // Creates two middle-right legs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 6); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates two middle-right foots. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 7); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates the right front thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(1.4f, -0.1f, -0.6f)); + + // Creates the right front leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10, rank); + m_object->SetObjectParent(10, 9); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates the right front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(11, rank); + m_object->SetObjectParent(11, 10); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates a left-back thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(12, rank); + m_object->SetObjectParent(12, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(12, D3DVECTOR(-0.4f, -0.1f, 0.3f)); + + // Creates a left-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(13, rank); + m_object->SetObjectParent(13, 12); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, 1.0f)); + + // Creates a left-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(14, rank); + m_object->SetObjectParent(14, 13); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(14, D3DVECTOR(0.0f, 0.0f, 2.0f)); + + // Creates two middle-left thighs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(15, rank); + m_object->SetObjectParent(15, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(15, D3DVECTOR(0.1f, -0.1f, 0.4f)); + + // Creates two middle-left legs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(16, rank); + m_object->SetObjectParent(16, 15); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(16, D3DVECTOR(0.0f, 0.0f, 1.0f)); + + // Creates two middle-left foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(17, rank); + m_object->SetObjectParent(17, 16); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(17, D3DVECTOR(0.0f, 0.0f, 2.0f)); + + // Creates the left front thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(18, rank); + m_object->SetObjectParent(18, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(18, D3DVECTOR(1.4f, -0.1f, 0.6f)); + + // Creates the left front leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(19, rank); + m_object->SetObjectParent(19, 18); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(19, D3DVECTOR(0.0f, 0.0f, 1.0f)); + + // Creates the left front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(20, rank); + m_object->SetObjectParent(20, 19); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(20, D3DVECTOR(0.0f, 0.0f, 2.0f)); + + m_object->CreateShadowCircle(4.0f, 0.5f); + + CreatePhysics(); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physics of the object. + +void CMotionAnt::CreatePhysics() +{ + Character* character; + int i; + + int member_march[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3 + 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3 + -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3 + // on the ground: + 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3 + -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3 + -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3 + // on the ground back: + 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3 + -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3 + -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3 + }; + + int member_stop[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3 + // on the ground: + 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3 + // on the ground back: + 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3 + }; + + int member_spec[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire: + 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3 + -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3 + -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3 + // shot: + 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3 + -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3 + -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3 + // ends the fire: + 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3 + -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3 + -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3 + // burning: + 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3 + // destroyed: + 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3 + // back1 : + 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3 + // back2 : + 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3 + -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3 + -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3 + // back3 : + 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3 + -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3 + -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3 + }; + + m_physics->SetType(TYPE_ROLLING); + + character = m_object->RetCharacter(); + character->wheelFront = 3.0f; + character->wheelBack = 3.0f; + character->wheelLeft = 5.0f; + character->wheelRight = 5.0f; + character->height = 1.2f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 12.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 15.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 20.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 40.0f); + + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i]; + } + for ( i=0 ; i<3*3*3*8 ; i++ ) + { + m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i]; + } +} + + +// Management of an event. + +BOOL CMotionAnt::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ANGLE + int i; + + if ( event.param == 'A' ) m_armTimeIndex++; + if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0; + + if ( event.param == 'Q' ) m_armPartIndex++; + if ( m_armPartIndex >= 3 ) m_armPartIndex = 0; + + if ( event.param == 'W' ) m_armMemberIndex++; + if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0; + + i = m_armMemberIndex*3; + i += m_armPartIndex*3*3; + i += m_armTimeIndex*3*3*3; +//? i += 3*3*3*3; + + if ( event.param == 'E' ) m_armAngles[i+0] += 5; + if ( event.param == 'D' ) m_armAngles[i+0] -= 5; + if ( event.param == 'R' ) m_armAngles[i+1] += 5; + if ( event.param == 'F' ) m_armAngles[i+1] -= 5; + if ( event.param == 'T' ) m_armAngles[i+2] += 5; + if ( event.param == 'G' ) m_armAngles[i+2] -= 5; + + if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop; +#endif + } + + return TRUE; +} + +// Calculates a value (radians) proportional between a and b (degrees). + +inline float Propf(float a, float b, float p) +{ + float aa, bb; + + aa = a*PI/180.0f; + bb = b*PI/180.0f; + + return aa+p*(bb-aa); +} + +// Management of an event. + +BOOL CMotionAnt::EventFrame(const Event &event) +{ + D3DVECTOR dir, pos, speed; + FPOINT dim; + float s, a, prog, time; + float tSt[9], tNd[9]; + int i, ii, st, nd, action; + BOOL bStop; + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f; + a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f); + + if ( s == 0.0f && a != 0.0f ) a *= 1.5f; + + m_armTimeAbs += event.rTime; + m_armTimeMarch += (s)*event.rTime*0.15f; + m_armMember += (s+a)*event.rTime*0.15f; + + bStop = ( a == 0.0f && s == 0.0f ); // stopped? + + action = MA_MARCH; // walking + if ( s == 0.0f && a == 0.0f ) + { + action = MA_STOP; // stop + } + + if ( bStop ) + { + prog = Mod(m_armTimeAbs, 2.0f)/10.0f; + a = Mod(m_armMember, 1.0f); + a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly + m_armMember += a; + } + + if ( m_object->RetRuin() ) // destroyed? + { + m_actionType = MAS_RUIN; + } + if ( m_object->RetBurn() ) // burning? + { + if ( m_object->RetFixed() ) + { + m_actionType = MAS_BURN; + } + else + { + m_actionType = -1; + } + } + + for ( i=0 ; i<6 ; i++ ) // the six legs + { + if ( m_actionType != -1 ) // special action in progress? + { + st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3; + nd = st; + time = event.rTime*m_actionTime; + m_armTimeAction = 0.0f; + } + else + { + if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f); + else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f); + if ( m_bArmStop ) + { + prog = (float)m_armTimeIndex/3.0f; + } + if ( prog < 0.33f ) // t0..t1 ? + { + prog = prog/0.33f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.67f ) // t1..t2 ? + { + prog = (prog-0.33f)/0.33f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.67f)/0.33f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + st = 3*3*3*3*action + st*3*3*3 + (i%3)*3; + nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3; + + // More and more soft ... + time = event.rTime*(10.0f+Min(m_armTimeAction*100.0f, 200.0f)); + } + + tSt[0] = m_armAngles[st+ 0]; // x + tSt[1] = m_armAngles[st+ 1]; // y + tSt[2] = m_armAngles[st+ 2]; // z + tSt[3] = m_armAngles[st+ 9]; // x + tSt[4] = m_armAngles[st+10]; // y + tSt[5] = m_armAngles[st+11]; // z + tSt[6] = m_armAngles[st+18]; // x + tSt[7] = m_armAngles[st+19]; // y + tSt[8] = m_armAngles[st+20]; // z + + tNd[0] = m_armAngles[nd+ 0]; // x + tNd[1] = m_armAngles[nd+ 1]; // y + tNd[2] = m_armAngles[nd+ 2]; // z + tNd[3] = m_armAngles[nd+ 9]; // x + tNd[4] = m_armAngles[nd+10]; // y + tNd[5] = m_armAngles[nd+11]; // z + tNd[6] = m_armAngles[nd+18]; // x + tNd[7] = m_armAngles[nd+19]; // y + tNd[8] = m_armAngles[nd+20]; // z + + if ( m_actionType == MAS_BACK2 ) // on the back? + { + for ( ii=0 ; ii<9 ; ii++ ) + { + tSt[ii] += Rand()*50.0f; + tNd[ii] = tSt[ii]; + } +//? time = 100.0f; + time = event.rTime*10.0f; + } + + if ( i < 3 ) // right leg (1..3) ? + { + m_object->SetAngleX(3+3*i+0, Smooth(m_object->RetAngleX(3+3*i+0), Propf(tSt[0], tNd[0], prog), time)); + m_object->SetAngleY(3+3*i+0, Smooth(m_object->RetAngleY(3+3*i+0), Propf(tSt[1], tNd[1], prog), time)); + m_object->SetAngleZ(3+3*i+0, Smooth(m_object->RetAngleZ(3+3*i+0), Propf(tSt[2], tNd[2], prog), time)); + m_object->SetAngleX(3+3*i+1, Smooth(m_object->RetAngleX(3+3*i+1), Propf(tSt[3], tNd[3], prog), time)); + m_object->SetAngleY(3+3*i+1, Smooth(m_object->RetAngleY(3+3*i+1), Propf(tSt[4], tNd[4], prog), time)); + m_object->SetAngleZ(3+3*i+1, Smooth(m_object->RetAngleZ(3+3*i+1), Propf(tSt[5], tNd[5], prog), time)); + m_object->SetAngleX(3+3*i+2, Smooth(m_object->RetAngleX(3+3*i+2), Propf(tSt[6], tNd[6], prog), time)); + m_object->SetAngleY(3+3*i+2, Smooth(m_object->RetAngleY(3+3*i+2), Propf(tSt[7], tNd[7], prog), time)); + m_object->SetAngleZ(3+3*i+2, Smooth(m_object->RetAngleZ(3+3*i+2), Propf(tSt[8], tNd[8], prog), time)); + } + else // left leg (4..6) ? + { + m_object->SetAngleX(3+3*i+0, Smooth(m_object->RetAngleX(3+3*i+0), Propf(-tSt[0], -tNd[0], prog), time)); + m_object->SetAngleY(3+3*i+0, Smooth(m_object->RetAngleY(3+3*i+0), Propf(-tSt[1], -tNd[1], prog), time)); + m_object->SetAngleZ(3+3*i+0, Smooth(m_object->RetAngleZ(3+3*i+0), Propf( tSt[2], tNd[2], prog), time)); + m_object->SetAngleX(3+3*i+1, Smooth(m_object->RetAngleX(3+3*i+1), Propf(-tSt[3], -tNd[3], prog), time)); + m_object->SetAngleY(3+3*i+1, Smooth(m_object->RetAngleY(3+3*i+1), Propf(-tSt[4], -tNd[4], prog), time)); + m_object->SetAngleZ(3+3*i+1, Smooth(m_object->RetAngleZ(3+3*i+1), Propf( tSt[5], tNd[5], prog), time)); + m_object->SetAngleX(3+3*i+2, Smooth(m_object->RetAngleX(3+3*i+2), Propf(-tSt[6], -tNd[6], prog), time)); + m_object->SetAngleY(3+3*i+2, Smooth(m_object->RetAngleY(3+3*i+2), Propf(-tSt[7], -tNd[7], prog), time)); + m_object->SetAngleZ(3+3*i+2, Smooth(m_object->RetAngleZ(3+3*i+2), Propf( tSt[8], tNd[8], prog), time)); + } + } + +#if ADJUST_ANGLE + if ( m_object->RetSelect() ) + { + char s[100]; + sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex); + m_engine->SetInfoText(4, s); + } +#endif + + if ( m_actionType == MAS_PREPARE ) // prepares the shooting? + { + prog = m_progress; + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = Prop(0, -50, prog); + SetInclinaison(dir); + m_object->SetAngleZ(1, Prop(0, 65, prog)); // head + m_object->SetAngleZ(2, Prop(0, -95, prog)); // tail + } + else if ( m_actionType == MAS_FIRE ) // shooting? + { + if ( m_progress < 0.75f ) a = m_progress/0.75f; + else a = (1.0f-m_progress)/0.25f; + m_object->SetZoom(2, (a*0.5f)+1.0f); // tail + m_object->SetAngleX(2, (Rand()-0.5f)*0.3f*a); + m_object->SetAngleY(2, (Rand()-0.5f)*0.3f*a); + + dir.x = (Rand()-0.5f)*0.02f*a; + dir.y = (Rand()-0.5f)*0.05f*a; + dir.z = (Rand()-0.5f)*0.03f*a; + SetCirVibration(dir); + } + else if ( m_actionType == MAS_TERMINATE ) // ends the shooting? + { + prog = 1.0f-m_progress; + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = Prop(0, -50, prog); + SetInclinaison(dir); + m_object->SetAngleZ(1, Prop(0, 65, prog)); // head + m_object->SetAngleZ(2, Prop(0, -95, prog)); // tail + } + else if ( m_actionType == MAS_BURN ) // burning? + { + dir = D3DVECTOR(PI, 0.0f, 0.0f); + SetCirVibration(dir); + dir = D3DVECTOR(0.0f, -1.5f, 0.0f); + SetLinVibration(dir); + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + time = event.rTime*1.0f; + m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head + m_object->SetAngleZ(2, Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail + } + else if ( m_actionType == MAS_RUIN ) // destroyed? + { + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + SetCirVibration(dir); + SetInclinaison(dir); + } + else if ( m_actionType == MAS_BACK1 ) // starts on the back? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress < 0.5f ) + { + dir.x = 0.0f; + dir.y = powf(m_progress/0.5f, 2.0f)*12.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + else + { + dir.x = 0.0f; + dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + dir.x = m_progress*PI; + dir.y = 0.0f; + dir.z = 0.0f; + SetCirVibration(dir); + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + if ( m_progress >= 1.0f ) + { + SetAction(MAS_BACK2, 55.0f+Rand()*10.0f); + } + } + else if ( m_actionType == MAS_BACK2 ) // moves on the back? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + if ( rand()%10 == 0 ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + pos.y -= 1.0f; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = (Rand()-0.5f)*2.0f; + speed.y = Rand()*2.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + } + + dir = D3DVECTOR(0.0f, -1.0f, 0.0f); + SetLinVibration(dir); + dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+ + sinf(m_armTimeAbs* 7.0f)*0.20f+ + sinf(m_armTimeAbs*10.0f)*0.40f+ + sinf(m_armTimeAbs*21.0f)*0.50f+PI; + dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+ + sinf(m_armTimeAbs* 6.0f)*0.02f+ + sinf(m_armTimeAbs*11.0f)*0.04f+ + sinf(m_armTimeAbs*20.0f)*0.02f; + dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+ + sinf(m_armTimeAbs* 8.0f)*0.02f+ + sinf(m_armTimeAbs* 9.0f)*0.04f+ + sinf(m_armTimeAbs*23.0f)*0.03f; + SetCirVibration(dir); + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head + m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail + m_object->SetAngleZ(1, 0.0f); // head + m_object->SetAngleZ(2, 0.0f); // tail + + if ( m_progress >= 1.0f ) + { + SetAction(MAS_BACK3, 0.4f); + } + } + else if ( m_actionType == MAS_BACK3 ) // goes back on the legs? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress < 0.5f ) + { + dir.x = 0.0f; + dir.y = powf(m_progress/0.5f, 2.0f)*5.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + else + { + dir.x = 0.0f; + dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + dir.x = (1.0f-m_progress)*PI; + dir.y = 0.0f; + dir.z = 0.0f; + SetCirVibration(dir); + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + if ( m_progress >= 1.0f ) + { + SetAction(-1); + m_object->SetFixed(FALSE); // moving again + } + } + else + { + m_object->SetZoom(2, 1.0f); // tail + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleY(2, 0.0f); + + if ( bStop ) + { + m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + SetInclinaison(dir); + } + else + { + a = Mod(m_armTimeMarch, 1.0f); + if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1 + else a = 3.0f-4.0f*a; // 1..-1 + dir.x = sinf(a)*0.05f; + + s = Mod(m_armTimeMarch/2.0f, 1.0f); + if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1 + else s = 3.0f-4.0f*s; // 1..-1 + dir.z = sinf(s)*0.1f; + + dir.y = 0.0f; + SetInclinaison(dir); + + m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail + + a = Mod(m_armMember-0.1f, 1.0f); + if ( a < 0.33f ) + { + dir.y = -(1.0f-(a/0.33f))*0.3f; + } + else if ( a < 0.67f ) + { + dir.y = 0.0f; + } + else + { + dir.y = -(a-0.67f)/0.33f*0.3f; + } + dir.x = 0.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetCirVibration(dir); + + m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head + m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head + } + + return TRUE; +} + + diff --git a/src/object/motion/motionant.h b/src/object/motion/motionant.h new file mode 100644 index 0000000..e8d79c6 --- /dev/null +++ b/src/object/motion/motionant.h @@ -0,0 +1,80 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionant.h + +#ifndef _MOTIONANT_H_ +#define _MOTIONANT_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +#define MA_MARCH 0 +#define MA_STOP 1 +#define MA_SPEC 2 + +#define MAS_PREPARE 0 +#define MAS_FIRE 1 +#define MAS_TERMINATE 2 +#define MAS_BURN 3 +#define MAS_RUIN 4 +#define MAS_BACK1 5 +#define MAS_BACK2 6 +#define MAS_BACK3 7 + + +class CMotionAnt : public CMotion +{ +public: + CMotionAnt(CInstanceManager* iMan, CObject* object); + ~CMotionAnt(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + +protected: + void CreatePhysics(); + BOOL EventFrame(const Event &event); + +protected: + float m_armMember; + float m_armTimeAbs; + float m_armTimeMarch; + float m_armTimeAction; + short m_armAngles[3*3*3*3*3 + 3*3*3*8]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + BOOL m_bArmStop; + float m_lastParticule; +}; + + +#endif //_MOTIONANT_H_ diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp new file mode 100644 index 0000000..65ebeb7 --- /dev/null +++ b/src/object/motion/motionbee.cpp @@ -0,0 +1,663 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionbee.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionbee.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeMarch = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLastAction = -1; + m_bArmStop = FALSE; +} + +// Object's destructor. + +CMotionBee::~CMotionBee() +{ +} + + +// Removes an object. + +void CMotionBee::DeleteObject(BOOL bAll) +{ +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionBee::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 3+18+2 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + + pModFile->ReadModel("objects\\bee1.mod"); + pModFile->CreateEngineObject(rank); + + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have an obligatory collision + // with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(-1.0f, 1.0f, 0.0f), 5.0f); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\bee2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(1.6f, 0.3f, 0.0f)); + + // Creates the tail. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\bee3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(-0.8f, 0.0f, 0.0f)); + + // Creates a right-back thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(-0.3f, -0.1f, -0.2f)); + + // Creates a right-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 3); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates a right-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates two middle-right thighs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.3f, -0.1f, -0.4f)); + + // Creates two middle-right legs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 6); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates two middle-right feet. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 7); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates the right front thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(1.0f, -0.1f, -0.7f)); + + // Creates the right front leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10, rank); + m_object->SetObjectParent(10, 9); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates the right front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(11, rank); + m_object->SetObjectParent(11, 10); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates a left-back thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(12, rank); + m_object->SetObjectParent(12, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(12, D3DVECTOR(-0.3f, -0.1f, 0.2f)); + m_object->SetAngleY(12, PI); + + // Creates a left-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(13, rank); + m_object->SetObjectParent(13, 12); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates a left-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(14, rank); + m_object->SetObjectParent(14, 13); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(14, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates two middle-left thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(15, rank); + m_object->SetObjectParent(15, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(15, D3DVECTOR(0.3f, -0.1f, 0.4f)); + m_object->SetAngleY(15, PI); + + // Creates two middle-left legs. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(16, rank); + m_object->SetObjectParent(16, 15); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(16, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates two middle-left feet. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(17, rank); + m_object->SetObjectParent(17, 16); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(17, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates front-left thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(18, rank); + m_object->SetObjectParent(18, 0); + pModFile->ReadModel("objects\\ant4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(18, D3DVECTOR(1.0f, -0.1f, 0.7f)); + m_object->SetAngleY(18, PI); + + // Creates front-left leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(19, rank); + m_object->SetObjectParent(19, 18); + pModFile->ReadModel("objects\\ant5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(19, D3DVECTOR(0.0f, 0.0f, -1.0f)); + + // Creates front-left foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(20, rank); + m_object->SetObjectParent(20, 19); + pModFile->ReadModel("objects\\ant6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(20, D3DVECTOR(0.0f, 0.0f, -2.0f)); + + // Creates the right wing. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(21, rank); + m_object->SetObjectParent(21, 0); + pModFile->ReadModel("objects\\bee7.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(21, D3DVECTOR(0.8f, 0.4f, -0.5f)); + + // Creates the left wing. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(22, rank); + m_object->SetObjectParent(22, 0); + pModFile->ReadModel("objects\\bee7.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(22, D3DVECTOR(0.8f, 0.4f, 0.5f)); + + m_object->CreateShadowCircle(6.0f, 0.5f); + + CreatePhysics(); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physical object. + +void CMotionBee::CreatePhysics() +{ + Character* character; + int i; + + int member_march[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3 + 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3 + -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3 + // on the ground: + 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3 + -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3 + -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3 + // on the ground back: + 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3 + -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3 + -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3 + }; + + int member_spec[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier: + 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3 + -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3 + -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3 + // burning: + 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3 + -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3 + -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3 + // destroyed: + 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3 + -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3 + -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3 + }; + + m_physics->SetType(TYPE_FLYING); + + character = m_object->RetCharacter(); + character->wheelFront = 3.0f; + character->wheelBack = 3.0f; + character->wheelLeft = 5.0f; + character->wheelRight = 5.0f; + character->height = 2.5f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 50.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 20.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f); + m_physics->SetLinMotionY(MO_RECSPEED, 60.0f); + m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionY(MO_RECACCEL, 50.0f); + m_physics->SetLinMotionY(MO_STOACCEL, 50.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 20.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 40.0f); + + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i]; + } +} + + +// Management of an event. + +BOOL CMotionBee::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ANGLE + int i; + + if ( event.param == 'A' ) m_armTimeIndex++; + if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0; + + if ( event.param == 'Q' ) m_armPartIndex++; + if ( m_armPartIndex >= 3 ) m_armPartIndex = 0; + + if ( event.param == 'W' ) m_armMemberIndex++; + if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0; + + i = m_armMemberIndex*3; + i += m_armPartIndex*3*3; + i += m_armTimeIndex*3*3*3; +//? i += 3*3*3*3; + + if ( event.param == 'E' ) m_armAngles[i+0] += 5; + if ( event.param == 'D' ) m_armAngles[i+0] -= 5; + if ( event.param == 'R' ) m_armAngles[i+1] += 5; + if ( event.param == 'F' ) m_armAngles[i+1] -= 5; + if ( event.param == 'T' ) m_armAngles[i+2] += 5; + if ( event.param == 'G' ) m_armAngles[i+2] -= 5; + + if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop; +#endif + } + + return TRUE; +} + +// Management of an event. + +BOOL CMotionBee::EventFrame(const Event &event) +{ + D3DVECTOR dir; + float s, a, prog; + int action, i, st, nd; + BOOL bStop; + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f; + a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f); + + if ( s == 0.0f && a != 0.0f ) a *= 1.5f; + + m_armTimeAbs += event.rTime; + m_armTimeMarch += (s)*event.rTime*0.15f; + m_armMember += (s+a)*event.rTime*0.15f; + + bStop = ( a == 0.0f && s == 0.0f ); // stopped? + if ( !m_physics->RetLand() ) bStop = TRUE; + + if ( bStop ) + { + prog = Mod(m_armTimeAbs, 2.0f)/10.0f; + a = Mod(m_armMember, 1.0f); + a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly + m_armMember += a; + } + + action = MB_MARCH; // flying + + m_actionType = -1; + if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball + + if ( m_object->RetRuin() ) // destroyed? + { + m_actionType = MBS_RUIN; + } + if ( m_object->RetBurn() ) // burning? + { + m_actionType = MBS_BURN; + } + + for ( i=0 ; i<6 ; i++ ) // the six legs + { + if ( m_actionType != -1 ) // special action in progress? + { + st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3; + nd = st; + } + else + { + if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f); + else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f); + if ( m_bArmStop ) + { + prog = (float)m_armTimeIndex/3.0f; + } + if ( prog < 0.33f ) // t0..t1 ? + { + prog = prog/0.33f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.67f ) // t1..t2 ? + { + prog = (prog-0.33f)/0.33f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.67f)/0.33f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + st = 3*3*3*3*action + st*3*3*3 + (i%3)*3; + nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3; + } + + if ( i < 3 ) // right leg (1..3) ? + { + m_object->SetAngleX(3+3*i+0, Prop(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog)); + m_object->SetAngleY(3+3*i+0, Prop(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog)); + m_object->SetAngleZ(3+3*i+0, Prop(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog)); + m_object->SetAngleX(3+3*i+1, Prop(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog)); + m_object->SetAngleY(3+3*i+1, Prop(m_armAngles[st+10], m_armAngles[nd+10], prog)); + m_object->SetAngleZ(3+3*i+1, Prop(m_armAngles[st+11], m_armAngles[nd+11], prog)); + m_object->SetAngleX(3+3*i+2, Prop(m_armAngles[st+18], m_armAngles[nd+18], prog)); + m_object->SetAngleY(3+3*i+2, Prop(m_armAngles[st+19], m_armAngles[nd+19], prog)); + m_object->SetAngleZ(3+3*i+2, Prop(m_armAngles[st+20], m_armAngles[nd+20], prog)); + } + else // left leg(4..6) ? + { + m_object->SetAngleX(3+3*i+0, Prop( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog)); + m_object->SetAngleY(3+3*i+0, Prop(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog)); + m_object->SetAngleZ(3+3*i+0, Prop( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog)); + m_object->SetAngleX(3+3*i+1, Prop( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog)); + m_object->SetAngleY(3+3*i+1, Prop( -m_armAngles[st+10], -m_armAngles[nd+10], prog)); + m_object->SetAngleZ(3+3*i+1, Prop( -m_armAngles[st+11], -m_armAngles[nd+11], prog)); + m_object->SetAngleX(3+3*i+2, Prop( m_armAngles[st+18], m_armAngles[nd+18], prog)); + m_object->SetAngleY(3+3*i+2, Prop( -m_armAngles[st+19], -m_armAngles[nd+19], prog)); + m_object->SetAngleZ(3+3*i+2, Prop( -m_armAngles[st+20], -m_armAngles[nd+20], prog)); + } + } + +#if ADJUST_ANGLE + if ( m_object->RetSelect() ) + { + char s[100]; + sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex); + m_engine->SetInfoText(4, s); + } +#endif + + if ( m_physics->RetLand() ) // on the ground? + { + if ( m_object->RetRuin() ) + { + } + else if ( bStop || m_object->RetBurn() ) + { + m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail + } + else + { + a = Mod(m_armTimeMarch, 1.0f); + if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1 + else a = 3.0f-4.0f*a; // 1..-1 + dir.x = sinf(a)*0.05f; + + s = Mod(m_armTimeMarch/2.0f, 1.0f); + if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1 + else s = 3.0f-4.0f*s; // 1..-1 + dir.z = sinf(s)*0.1f; + + dir.y = 0.0f; + m_object->SetInclinaison(dir); + + m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail + + a = Mod(m_armMember-0.1f, 1.0f); + if ( a < 0.33f ) + { + dir.y = -(1.0f-(a/0.33f))*0.3f; + } + else if ( a < 0.67f ) + { + dir.y = 0.0f; + } + else + { + dir.y = -(a-0.67f)/0.33f*0.3f; + } + dir.x = 0.0f; + dir.z = 0.0f; + m_object->SetLinVibration(dir); + } + } + + if ( m_physics->RetLand() ) + { + if ( bStop ) prog = 0.05f; + else prog = 0.15f; + } + else + { + prog = 1.00f; + } + +#if 0 + a = Rand()*PI/2.0f*prog; + m_object->SetAngleX(21, a); // right wing + a = -Rand()*PI/4.0f*prog; + m_object->SetAngleY(21, a); + + a = -Rand()*PI/2.0f*prog; + m_object->SetAngleX(22, a); // left wing + a = Rand()*PI/4.0f*prog; + m_object->SetAngleY(22, a); +#else + m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(PI/4.0f)*prog); + m_object->SetAngleY(21, -Rand()*PI/6.0f*prog); + + m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(PI/4.0f)*prog); + m_object->SetAngleY(22, Rand()*PI/6.0f*prog); +#endif + + m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head + m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head + +#if 0 + h = m_terrain->RetFloorHeight(RetPosition(0)); + radius = 4.0f+h/4.0f; + color.r = 0.3f+h/80.0f; + color.g = color.r; + color.b = color.r; + color.a = color.r; + m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius); + m_engine->SetObjectShadowColor(m_objectPart[0].object, color); +#endif + + return TRUE; +} + + diff --git a/src/object/motion/motionbee.h b/src/object/motion/motionbee.h new file mode 100644 index 0000000..facf650 --- /dev/null +++ b/src/object/motion/motionbee.h @@ -0,0 +1,73 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionbee.h + +#ifndef _MOTIONBEE_H_ +#define _MOTIONBEE_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +#define MB_MARCH 0 +#define MB_SPEC 1 + +#define MBS_HOLD 0 +#define MBS_BURN 1 +#define MBS_RUIN 2 + + +class CMotionBee : public CMotion +{ +public: + CMotionBee(CInstanceManager* iMan, CObject* object); + ~CMotionBee(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + +protected: + void CreatePhysics(); + BOOL EventFrame(const Event &event); + +protected: + float m_armMember; + float m_armTimeAbs; + float m_armTimeMarch; + float m_armTimeAction; + short m_armAngles[3*3*3*3*2]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + BOOL m_bArmStop; +}; + + +#endif //_MOTIONBEE_H_ diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp new file mode 100644 index 0000000..78750fa --- /dev/null +++ b/src/object/motion/motionhuman.cpp @@ -0,0 +1,1799 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionhuman.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "robotmain.h" +#include "sound.h" +#include "motion.h" +#include "motionhuman.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members +#define ADJUST_ACTION (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM) + +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_partiReactor = -1; + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeSwim = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLastAction = -1; + m_bArmStop = FALSE; + m_lastSoundMarch = 0.0f; + m_lastSoundHhh = 0.0f; + m_time = 0.0f; + m_tired = 0.0f; + m_bDisplayPerso = FALSE; +} + +// Object's constructor. + +CMotionHuman::~CMotionHuman() +{ +} + + +// Removes an object. + +void CMotionHuman::DeleteObject(BOOL bAll) +{ + if ( m_partiReactor != -1 ) + { + m_particule->DeleteParticule(m_partiReactor); + m_partiReactor = -1; + } +} + + +// Starts an action. + +Error CMotionHuman::SetAction(int action, float time) +{ + CMotion::SetAction(action, time); + m_time = 0.0f; + return ERR_OK; +} + + +// Creates cosmonaut on the ground. + +BOOL CMotionHuman::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + char filename[100]; + int rank, option, face, glasses; + + if ( m_engine->RetRestCreate() < 16 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + option = m_object->RetOption(); + + if ( m_main->RetGamerOnlyHead() ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + face = m_main->RetGamerFace(); + sprintf(filename, "objects\\human2h%d.mod", face+1); + pModFile->ReadModel(filename); + pModFile->CreateEngineObject(rank); + + glasses = m_main->RetGamerGlasses(); + if ( glasses != 0 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + sprintf(filename, "objects\\human2g%d.mod", glasses); + pModFile->ReadModel(filename); + pModFile->CreateEngineObject(rank); + } + + CreatePhysics(type); + m_object->SetFloorHeight(0.0f); + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; + } + + // Creates the main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + + if ( option == 0 ) // head in helmet? + { + pModFile->ReadModel("objects\\human1c.mod"); + } + if ( option == 1 ) // head without helmet? + { + pModFile->ReadModel("objects\\human1h.mod"); + } + if ( option == 2 ) // without a backpack? + { + pModFile->ReadModel("objects\\human1v.mod"); + } + pModFile->CreateEngineObject(rank); + + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 4.0f); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + + if ( type == OBJECT_HUMAN ) + { + if ( option == 0 ) // head in helmet? + { + face = m_main->RetGamerFace(); + sprintf(filename, "objects\\human2c%d.mod", face+1); + pModFile->ReadModel(filename); + } + if ( option == 1 || // head without helmet? + option == 2 ) // without a backpack? + { + face = m_main->RetGamerFace(); + sprintf(filename, "objects\\human2h%d.mod", face+1); + pModFile->ReadModel(filename); + } + } + if ( type == OBJECT_TECH ) + { + pModFile->ReadModel("objects\\human2t.mod"); + } + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 2.7f, 0.0f)); + if ( option == 1 || // head without helmet? + option == 2 ) // without a backpack? + { + m_object->SetZoom(1, D3DVECTOR(1.0f, 1.05f, 1.0f)); + } + + // Creates the glasses. + glasses = m_main->RetGamerGlasses(); + if ( glasses != 0 && type == OBJECT_HUMAN ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(15, rank); + m_object->SetObjectParent(15, 1); + sprintf(filename, "objects\\human2g%d.mod", glasses); + pModFile->ReadModel(filename); + pModFile->CreateEngineObject(rank); + } + + // Creates the right arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\human3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(0.0f, 2.3f, -1.2f)); + m_object->SetAngle(2, D3DVECTOR(90.0f*PI/180.0f, 90.0f*PI/180.0f, -50.0f*PI/180.0f)); + + // Creates the right forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\human4r.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(1.3f, 0.0f, 0.0f)); + m_object->SetAngle(3, D3DVECTOR(0.0f*PI/180.0f, -20.0f*PI/180.0f, 0.0f*PI/180.0f)); + + // Creates right hand. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 3); + pModFile->ReadModel("objects\\human5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(1.2f, 0.0f, 0.0f)); + + // Creates the right thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 0); + pModFile->ReadModel("objects\\human6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -0.7f)); + m_object->SetAngle(5, D3DVECTOR(10.0f*PI/180.0f, 0.0f*PI/180.0f, 5.0f*PI/180.0f)); + + // Creates the right leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 5); + pModFile->ReadModel("objects\\human7.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, -1.5f, 0.0f)); + m_object->SetAngle(6, D3DVECTOR(0.0f*PI/180.0f, 0.0f*PI/180.0f, -10.0f*PI/180.0f)); + + // Creates the right foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 6); + pModFile->ReadModel("objects\\human8.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, -1.5f, 0.0f)); + m_object->SetAngle(7, D3DVECTOR(-10.0f*PI/180.0f, 5.0f*PI/180.0f, 5.0f*PI/180.0f)); + + // Creates the left arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\human3.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(0.0f, 2.3f, 1.2f)); + m_object->SetAngle(8, D3DVECTOR(-90.0f*PI/180.0f, -90.0f*PI/180.0f, -50.0f*PI/180.0f)); + + // Creates the left forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 8); + pModFile->ReadModel("objects\\human4l.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(1.3f, 0.0f, 0.0f)); + m_object->SetAngle(9, D3DVECTOR(0.0f*PI/180.0f, 20.0f*PI/180.0f, 0.0f*PI/180.0f)); + + // Creates left hand. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10, rank); + m_object->SetObjectParent(10, 9); + pModFile->ReadModel("objects\\human5.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10, D3DVECTOR(1.2f, 0.0f, 0.0f)); + + // Creates the left thigh. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(11, rank); + m_object->SetObjectParent(11, 0); + pModFile->ReadModel("objects\\human6.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, 0.7f)); + m_object->SetAngle(11, D3DVECTOR(-10.0f*PI/180.0f, 0.0f*PI/180.0f, 5.0f*PI/180.0f)); + + // Creates the left leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(12, rank); + m_object->SetObjectParent(12, 11); + pModFile->ReadModel("objects\\human7.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(12, D3DVECTOR(0.0f, -1.5f, 0.0f)); + m_object->SetAngle(12, D3DVECTOR(0.0f*PI/180.0f, 0.0f*PI/180.0f, -10.0f*PI/180.0f)); + + // Creates the left foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(13, rank); + m_object->SetObjectParent(13, 12); + pModFile->ReadModel("objects\\human8.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(13, D3DVECTOR(0.0f, -1.5f, 0.0f)); + m_object->SetAngle(13, D3DVECTOR(10.0f*PI/180.0f, -5.0f*PI/180.0f, 5.0f*PI/180.0f)); + + // Creates the neutron gun. + if ( option != 2 ) // with backpack? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(14, rank); + m_object->SetObjectParent(14, 0); + pModFile->ReadModel("objects\\human9.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(14, D3DVECTOR(-1.5f, 0.3f, -1.35f)); + m_object->SetAngleZ(14, PI); + } + + m_object->CreateShadowCircle(2.0f, 0.8f); + + CreatePhysics(type); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physical object. + +void CMotionHuman::CreatePhysics(ObjectType type) +{ + Character* character; + int i; + + int member_march[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/- + 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/- + 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/- + // on the ground: + 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/- + 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/- + 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/- + // on the ground back: + 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/- + 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/- + 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/- + }; + + int member_march_take[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/- + 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/- + -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/- + // on the ground: + 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/- + 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/- + -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/- + // on the ground back: + 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/- + 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/- + -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/- + }; + + int member_turn[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/- + 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/- + 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/- + // on the ground: + 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/- + 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/- + 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/- + // on the ground back: + 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/- + 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/- + 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/- + }; + + int member_stop[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, + 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/- + 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // hands/feet/- + // + 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/- + 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // hands/feet/- + // + 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/- + 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // hands/feet/- + }; + + int member_fly[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, + -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/- + 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/- + 40,10,25, 0,15,0, 0,0,0, // hands/feet/- + // + -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/- + 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/- + 45,5,20, 0,15,0, 0,0,0, // hands/feet/- + // + -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/- + 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/- + 30,15,25, 0,15,0, 0,0,0, // hands/feet/- + }; + + int member_swim[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, +#if 1 + 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/- + 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/- + 0,0,0, -5,10,-5, 0,0,0, // hands/feet/- + // + 130,-95,115,55,5,5, 0,0,0, // arms/thighs/- + 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,5,-30, 0,0,0, // hands/feet/- + // + 130,-100,220,5,0,0, 0,0,0, // arms/thighs/- + 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,30,-20, 0,0,0, // hands/feet/- +#endif +#if 0 + 130,-70,200,5,0,0, 0,0,0, // arms/thighs/- + 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,30,-20, 0,0,0, // hands/feet/- + // + 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/- + 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/- + 0,0,0, -5,10,-5, 0,0,0, // hands/feet/- + // + 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/- + 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,5,-30, 0,0,0, // hands/feet/- +#endif +#if 0 + 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/- + 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,5,-30, 0,0,0, // hands/feet/- + // + 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/- + 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/- + 0,0,0, -5,30,-20, 0,0,0, // hands/feet/- + // + 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/- + 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/- + 0,0,0, -5,10,-5, 0,0,0, // hands/feet/- +#endif + }; + + int member_spec[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting: + 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/- + -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/- + 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/- + // takes weapon: + 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/- + 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/- + 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/- + // carries earth: + 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/- + 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/- + 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/- + // carries in front: + 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/- + -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/- + 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/- + // carries vertically: + -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/- + 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/- + 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/- + // rises: + 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/- + 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/- + -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/- + // wins: + 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/- + 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/- + 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/- + // lose: + -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/- + 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/- + 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/- + // shooting death (falls): + 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/- + 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/- + // shooting death (knees): + 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/- + 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/- + // shooting death (knees): + 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/- + 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/- + // shooting death (face down): + 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/- + 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/- + // shooting death (face down): + 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/- + 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/- + // drowned: + 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/- + 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/- + 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/- + // puts / removes flag: + 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/- + -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/- + 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/- + // reads SatCom: + 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/- + 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/- + 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/- + }; + + m_physics->SetType(TYPE_FLYING); + + character = m_object->RetCharacter(); + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.0f; + character->wheelRight = 4.0f; + character->height = 3.5f; + + if ( type == OBJECT_HUMAN ) + { + m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 35.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 20.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 70.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f); + m_physics->SetLinMotionY(MO_RECSPEED, 60.0f); + m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionY(MO_RECACCEL, 50.0f); + m_physics->SetLinMotionY(MO_STOACCEL, 50.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 6.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 4.0f); + } + else + { + m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 15.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 8.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 8.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f); + m_physics->SetLinMotionY(MO_RECSPEED, 60.0f); + m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionY(MO_RECACCEL, 50.0f); + m_physics->SetLinMotionY(MO_STOACCEL, 50.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 4.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 3.0f); + } + + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i]; + } + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i]; + } + for ( i=0 ; i<3*3*3*16 ; i++ ) + { + m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i]; + } +} + + +// Management of an event. + +BOOL CMotionHuman::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ANGLE + int i; + + if ( event.param == 'A' ) m_armTimeIndex++; + if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0; + + if ( event.param == 'Q' ) m_armPartIndex++; + if ( m_armPartIndex >= 3 ) m_armPartIndex = 0; + + if ( event.param == 'W' ) m_armMemberIndex++; + if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0; + + i = m_armMemberIndex*3; + i += m_armPartIndex*3*3; + i += m_armTimeIndex*3*3*3; + i += ADJUST_ACTION; + + if ( event.param == 'E' ) m_armAngles[i+0] += 5; + if ( event.param == 'D' ) m_armAngles[i+0] -= 5; + if ( event.param == 'R' ) m_armAngles[i+1] += 5; + if ( event.param == 'F' ) m_armAngles[i+1] -= 5; + if ( event.param == 'T' ) m_armAngles[i+2] += 5; + if ( event.param == 'G' ) m_armAngles[i+2] -= 5; + + if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop; + + if ( event.param == 'Y' ) + { + char s[100]; + sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18); + OutputDebugString(s); + } +#endif + } + + return TRUE; +} + +// Calculates a value (radians) proportional between a and b (degrees). + +inline float Propf(float a, float b, float p) +{ + float aa, bb; + + aa = a*PI/180.0f; + bb = b*PI/180.0f; + + return aa+p*(bb-aa); +} + +// Management of an event. + +BOOL CMotionHuman::EventFrame(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR dir, actual, pos, speed, pf; + FPOINT center, dim, p2; + float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl; + float al, ar, af; + float tSt[9], tNd[9]; + float aa, bb, shield, deadFactor, level; + int i, ii, st, nd, action, legAction, armAction; + BOOL bOnBoard, bSwim, bStop; + + if ( m_engine->RetPause() ) + { + if ( m_actionType == MHS_SATCOM ) + { + m_progress += event.rTime*m_actionTime; + } + else + { + return TRUE; + } + } + + bOnBoard = FALSE; + if ( m_object->RetSelect() && + m_camera->RetType() == CAMERA_ONBOARD ) + { + bOnBoard = TRUE; + } + + if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() ) + { + m_time += event.rTime; + m_object->SetLinVibration(D3DVECTOR(0.0f, -0.55f, 0.0f)); + m_object->SetCirVibration(D3DVECTOR(0.0f, m_main->RetPersoAngle(), 0.0f)); + return TRUE; + } + if ( m_bDisplayPerso ) + { + m_object->SetCirVibration(D3DVECTOR(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f)); + } + + shield = m_object->RetShield(); + shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds + if ( shield > 1.0f ) shield = 1.0f; + m_object->SetShield(shield); + + bSwim = m_physics->RetSwim(); + +#if 0 + rot = m_physics->RetCirMotionY(MO_MOTSPEED); + s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f; + a = m_physics->RetLinMotionX(MO_TERSPEED); + if ( a < 0.0f ) // rises? + { + if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly? +//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly? + } + if ( a > 0.0f && !bSwim ) // falls? + { + if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly? +//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly? + } + a = Abs(rot*12.0f); + + if ( !m_physics->RetLand() && !bSwim ) // in flight? + { + s = 0.0f; + } + + if ( m_object->RetFret() != 0 ) // carries something? + { + s *= 1.3f; + } +#else + rot = m_physics->RetCirMotionY(MO_MOTSPEED); +#if 0 + s = m_physics->RetLinMotionX(MO_REASPEED); +#else + a = m_physics->RetLinMotionX(MO_REASPEED); + s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f; + if ( Abs(a) > Abs(s) ) s = a; // the highest value +#endif + a = m_physics->RetLinMotionX(MO_TERSPEED); + if ( a < 0.0f ) // rises? + { + a += m_physics->RetLinMotionX(MO_TERSLIDE); + if ( a < 0.0f ) s -= a; + } + if ( a > 0.0f ) // falls? + { + a -= m_physics->RetLinMotionX(MO_TERSLIDE); + if ( a > 0.0f ) s -= a; + } + s *= 2.0f; + a = Abs(rot*12.0f); + + if ( !m_physics->RetLand() && !bSwim ) // in flight? + { + s = 0.0f; + } + + if ( m_object->RetFret() != 0 ) // carries something? + { + s *= 1.3f; + } +#endif + + m_time += event.rTime; + m_armTimeAbs += event.rTime; + m_armTimeAction += event.rTime; + m_armMember += s*event.rTime*0.05f; + + // Fatigue management when short. + if ( m_physics->RetLand() && s != 0.0f ) // on the ground? + { + m_tired += event.rTime*0.1f; + if ( m_tired > 1.0f ) + { + m_tired = 1.0f; + if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f; + } + } + else + { + m_tired -= event.rTime*0.2f; + if ( m_tired < 0.0f ) m_tired = 0.0f; + } + + if ( bSwim ) // swims? + { + s += Abs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f); + a *= 2.0f; + m_armTimeSwim += Min(Max(s,a,3.0f),15.0f)*event.rTime*0.05f; + } + + bStop = ( s == 0.0f ); // stop? + prog = 0.0f; + + if ( m_physics->RetLand() ) // on the ground? + { + if ( s == 0.0f && a == 0.0f ) + { + action = MH_STOP; // stop + rTime[0] = rTime[1] = m_armTimeAbs*0.21f; + lTime[0] = lTime[1] = m_armTimeAbs*0.25f; + m_armMember = START_TIME; + } + else + { + if ( s == 0.0f ) + { + action = MH_TURN; // turn + rTime[0] = rTime[1] = m_armTimeAbs; + lTime[0] = lTime[1] = m_armTimeAbs+0.5f; + if ( rot < 0.0f ) + { + rTime[1] = 1000000.0f-rTime[1]; + } + else + { + lTime[1] = 1000000.0f-lTime[1]; + } + m_armMember = START_TIME; + } + else + { + action = MH_MARCH; // walking + if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking + rTime[0] = rTime[1] = m_armMember; + lTime[0] = lTime[1] = m_armMember+0.5f; + } + } + if ( bSwim ) + { + rTime[0] *= 0.6f; + rTime[1] *= 0.6f; + lTime[0] = rTime[0]+0.5f; + lTime[1] = rTime[1]+0.5f; + } + } + else + { + if ( bSwim ) + { + action = MH_SWIM; // swim + rTime[0] = rTime[1] = m_armTimeSwim; + lTime[0] = lTime[1] = m_armTimeSwim; + } + else + { + action = MH_FLY; // fly + rTime[0] = rTime[1] = m_armTimeAbs*0.30f; + lTime[0] = lTime[1] = m_armTimeAbs*0.31f; + m_armMember = START_TIME; + } + } + + if ( action != m_armLastAction ) + { + m_armLastAction = action; + m_armTimeAction = 0.0f; + } + + armAction = action; + legAction = action; + + if ( m_object->RetFret() != 0 ) // carries something? + { + armAction = MH_MARCHTAKE; // take walking + } + + if ( m_physics->RetLand() ) // on the ground? + { + a = m_object->RetAngleY(0); + pos = m_object->RetPosition(0); + m_terrain->MoveOnFloor(pos); + + pf.x = pos.x+cosf(a+PI*1.5f)*0.7f; + pf.y = pos.y; + pf.z = pos.z-sinf(a+PI*1.5f)*0.7f; + m_terrain->MoveOnFloor(pf); + al = atanf((pf.y-pos.y)/0.7f); // angle for left leg + + pf = pos; + pf.x = pos.x+cosf(a+PI*0.5f)*0.7f; + pf.y = pos.y; + pf.z = pos.z-sinf(a+PI*0.5f)*0.7f; + m_terrain->MoveOnFloor(pf); + ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg + + pf.x = pos.x+cosf(a+PI)*0.3f; + pf.y = pos.y; + pf.z = pos.z-sinf(a+PI)*0.3f; + m_terrain->MoveOnFloor(pf); + af = atanf((pf.y-pos.y)/0.3f); // angle for feet + } + else + { + al = 0.0f; + ar = 0.0f; + af = 0.0f; + } + + for ( i=0 ; i<4 ; i++ ) // 4 members + { + if ( m_bArmStop ) // focus? + { + st = ADJUST_ACTION + (i%2)*3; + nd = st; + time = 100.0f; + m_armTimeAction = 0.0f; + } + else if ( m_actionType != -1 ) // special action in progress? + { + st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3; + nd = st; + time = event.rTime*m_actionTime; + m_armTimeAction = 0.0f; + } + else + { + if ( i < 2 ) prog = Mod(rTime[i%2], 1.0f); + else prog = Mod(lTime[i%2], 1.0f); + if ( prog < 0.25f ) // t0..t1 ? + { + prog = prog/0.25f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.75f ) // t1..t2 ? + { + prog = (prog-0.25f)/0.50f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.75f)/0.25f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + if ( i%2 == 0 ) // arm? + { + st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3; + nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3; + } + else // leg? + { + st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3; + nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3; + } + + // Less soft ... + time = event.rTime*(5.0f+Min(m_armTimeAction*50.0f, 100.0f)); + if ( bSwim ) time *= 0.25f; + } + + tSt[0] = m_armAngles[st+ 0]; // x + tSt[1] = m_armAngles[st+ 1]; // y + tSt[2] = m_armAngles[st+ 2]; // z + tSt[3] = m_armAngles[st+ 9]; // x + tSt[4] = m_armAngles[st+10]; // y + tSt[5] = m_armAngles[st+11]; // z + tSt[6] = m_armAngles[st+18]; // x + tSt[7] = m_armAngles[st+19]; // y + tSt[8] = m_armAngles[st+20]; // z + + tNd[0] = m_armAngles[nd+ 0]; // x + tNd[1] = m_armAngles[nd+ 1]; // y + tNd[2] = m_armAngles[nd+ 2]; // z + tNd[3] = m_armAngles[nd+ 9]; // x + tNd[4] = m_armAngles[nd+10]; // y + tNd[5] = m_armAngles[nd+11]; // z + tNd[6] = m_armAngles[nd+18]; // x + tNd[7] = m_armAngles[nd+19]; // y + tNd[8] = m_armAngles[nd+20]; // z + + aa = 0.5f; + if ( i%2 == 0 ) // arm? + { + if ( m_object->RetFret() == 0 ) // does nothing? + { + aa = 2.0f; // moves a lot + } + else + { + aa = 0.0f; // immobile + } + } + + if ( i < 2 ) // left? + { + bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb; + bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb; + bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb; + bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb; + bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb; + bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb; + bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb; + bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb; + bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb; + } + else // right? + { + bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb; + bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb; + bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb; + bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb; + bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb; + bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb; + bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb; + bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb; + bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb; + } + +#if 1 + if ( i%2 == 1 && // leg? + m_actionType == -1 ) // no special action? + { + if ( i == 1 ) // right leg? + { + ii = 5; + a = ar*0.25f; + } + else + { + ii = 11; + a = al*0.25f; + } + if ( a < -0.2f ) a = -0.2f; + if ( a > 0.2f ) a = 0.2f; + + pos = m_object->RetPosition(ii+0); + pos.y = 0.0f+a; + m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh + + pos = m_object->RetPosition(ii+1); + pos.y = -1.5f+a; + m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg + + pos = m_object->RetPosition(ii+2); + pos.y = -1.5f+a; + m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot + + if ( i == 1 ) // right leg? + { + aa = (ar*180.0f/PI*0.5f); + } + else // left leg? + { + aa = (al*180.0f/PI*0.5f); + } + tSt[6] += aa; + tNd[6] += aa; // increases the angle X of the foot + + if ( i == 1 ) // right leg? + { + aa = (ar*180.0f/PI); + } + else // left leg? + { + aa = (al*180.0f/PI); + } + if ( aa < 0.0f ) aa = 0.0f; + if ( aa > 30.0f ) aa = 30.0f; + + tSt[2] += aa; + tNd[2] += aa; // increases the angle Z of the thigh + tSt[5] -= aa*2; + tNd[5] -= aa*2; // increases the angle Z of the leg + tSt[8] += aa; + tNd[8] += aa; // increases the angle Z of the foot + + aa = (af*180.0f/PI)*0.7f; + if ( aa < -30.0f ) aa = -30.0f; + if ( aa > 30.0f ) aa = 30.0f; + + tSt[8] -= aa; + tNd[8] -= aa; // increases the angle Z of the foot + } +#endif + + if ( m_actionType == MHS_DEADw ) // drowned? + { + if ( m_progress < 0.5f ) + { + deadFactor = m_progress/0.5f; + } + else + { + deadFactor = 1.0f-(m_progress-0.5f)/0.5f; + } + if ( deadFactor < 0.0f ) deadFactor = 0.0f; + if ( deadFactor > 1.0f ) deadFactor = 1.0f; + + for ( ii=0 ; ii<9 ; ii++ ) + { + tSt[ii] += Rand()*20.0f*deadFactor; + tNd[ii] = tSt[ii]; + } + time = 100.0f; + } + + if ( i < 2 ) // right member (0..1) ? + { + m_object->SetAngleX(2+3*i+0, Smooth(m_object->RetAngleX(2+3*i+0), Propf(tSt[0], tNd[0], prog), time)); + m_object->SetAngleY(2+3*i+0, Smooth(m_object->RetAngleY(2+3*i+0), Propf(tSt[1], tNd[1], prog), time)); + m_object->SetAngleZ(2+3*i+0, Smooth(m_object->RetAngleZ(2+3*i+0), Propf(tSt[2], tNd[2], prog), time)); + m_object->SetAngleX(2+3*i+1, Smooth(m_object->RetAngleX(2+3*i+1), Propf(tSt[3], tNd[3], prog), time)); + m_object->SetAngleY(2+3*i+1, Smooth(m_object->RetAngleY(2+3*i+1), Propf(tSt[4], tNd[4], prog), time)); + m_object->SetAngleZ(2+3*i+1, Smooth(m_object->RetAngleZ(2+3*i+1), Propf(tSt[5], tNd[5], prog), time)); + m_object->SetAngleX(2+3*i+2, Smooth(m_object->RetAngleX(2+3*i+2), Propf(tSt[6], tNd[6], prog), time)); + m_object->SetAngleY(2+3*i+2, Smooth(m_object->RetAngleY(2+3*i+2), Propf(tSt[7], tNd[7], prog), time)); + m_object->SetAngleZ(2+3*i+2, Smooth(m_object->RetAngleZ(2+3*i+2), Propf(tSt[8], tNd[8], prog), time)); + } + else // left member (2..3) ? + { + m_object->SetAngleX(2+3*i+0, Smooth(m_object->RetAngleX(2+3*i+0), Propf(-tSt[0], -tNd[0], prog), time)); + m_object->SetAngleY(2+3*i+0, Smooth(m_object->RetAngleY(2+3*i+0), Propf(-tSt[1], -tNd[1], prog), time)); + m_object->SetAngleZ(2+3*i+0, Smooth(m_object->RetAngleZ(2+3*i+0), Propf( tSt[2], tNd[2], prog), time)); + m_object->SetAngleX(2+3*i+1, Smooth(m_object->RetAngleX(2+3*i+1), Propf(-tSt[3], -tNd[3], prog), time)); + m_object->SetAngleY(2+3*i+1, Smooth(m_object->RetAngleY(2+3*i+1), Propf(-tSt[4], -tNd[4], prog), time)); + m_object->SetAngleZ(2+3*i+1, Smooth(m_object->RetAngleZ(2+3*i+1), Propf( tSt[5], tNd[5], prog), time)); + m_object->SetAngleX(2+3*i+2, Smooth(m_object->RetAngleX(2+3*i+2), Propf(-tSt[6], -tNd[6], prog), time)); + m_object->SetAngleY(2+3*i+2, Smooth(m_object->RetAngleY(2+3*i+2), Propf(-tSt[7], -tNd[7], prog), time)); + m_object->SetAngleZ(2+3*i+2, Smooth(m_object->RetAngleZ(2+3*i+2), Propf( tSt[8], tNd[8], prog), time)); + } + } + +#if ADJUST_ANGLE + if ( m_object->RetSelect() ) + { + char s[100]; + sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex); + m_engine->SetInfoText(4, s); + } +#endif + + // calculates the height lowering as a function + // of the position of the legs. + hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) + + 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6))); + a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7)); + if ( a < 0.0f ) hr += a; + + hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) + + 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12))); + a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13)); + if ( a < 0.0f ) hl += a; + + hr = Min(hr, hl); + + if ( m_actionType == MHS_FIRE ) // shooting? + { + time = event.rTime*m_actionTime; + + dir.x = (Rand()-0.5f)/8.0f; + dir.z = (Rand()-0.5f)/8.0f; + dir.y = -0.5f; // slightly lower + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); +//? dir.y = Smooth(actual.y, dir.y, time); + dir.y = -hr; + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = (Rand()-0.5f)/3.0f; + dir.z = -0.1f; // slightly leaning forward + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_TAKE || // carrying? + m_actionType == MHS_TAKEOTHER ) // flag? + { + time = event.rTime*m_actionTime*2.0f; + + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = -1.5f; // slightly lower + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); +//? dir.y = Smooth(actual.y, dir.y, time); + dir.y = -hr; + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = -0.2f; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_TAKEHIGH ) // carrying? + { + time = event.rTime*m_actionTime*2.0f; + + dir.x = 0.4f; // slightly forward + dir.z = 0.0f; + dir.y = 0.0f; + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); +//? dir.y = Smooth(actual.y, dir.y, time); + dir.y = -hr; + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = -0.2f; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_FLAG ) // flag? + { + time = event.rTime*m_actionTime*2.0f; + + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = -2.0f; // slightly lower + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); +//? dir.y = Smooth(actual.y, dir.y, time); + dir.y = -hr; + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = -0.4f; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_DEADg ) // shooting death (falls)? + { + if ( m_physics->RetLand() ) // on the ground? + { + SetAction(MHS_DEADg1, 0.5f); // knees + } + } + else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)? + { + prog = m_progress; + if ( prog >= 1.0f ) + { + prog = 1.0f; + + for ( i=0 ; i<10 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*4.0f; + pos.z += (Rand()-0.5f)*4.0f; + m_terrain->MoveOnFloor(pos); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 1.2f+Rand()*1.2f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f); + } + m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0)); + + SetAction(MHS_DEADg2, 1.0f); // expects knees + } + + time = 100.0f; + + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = -1.5f*prog; + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = -(20.0f*PI/180.0f)*prog; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)? + { + if ( m_progress >= 1.0f ) + { + SetAction(MHS_DEADg3, 1.0f); // face down + } + + time = 100.0f; + + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = -1.5f; + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = -(20.0f*PI/180.0f); + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)? + { + prog = m_progress; + if ( prog >= 1.0f ) + { + prog = 1.0f; + + for ( i=0 ; i<20 ; i++ ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*8.0f; + pos.z += (Rand()-0.5f)*8.0f; + m_terrain->MoveOnFloor(pos); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f+Rand()*1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f); + } + m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0)); + + SetAction(MHS_DEADg4, 3.0f); // expects face down + } + + time = 100.0f; + prog = powf(prog, 3.0f); + + dir.y = -(1.5f+1.5f*prog); + dir.x = 0.0f; + dir.z = 0.0f; + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.z = -((20.0f*PI/180.0f)+(70.0f*PI/180.0f)*prog); + dir.x = 0.0f; + dir.y = 0.0f; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)? + { + if ( m_progress >= 1.0f ) + { + m_object->SetEnable(FALSE); + } + + time = 100.0f; + + dir.y = -(1.5f+1.5f); + dir.x = 0.0f; + dir.z = 0.0f; + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetLinVibration(dir); + + dir.z = -((20.0f*PI/180.0f)+(70.0f*PI/180.0f)); + dir.x = 0.0f; + dir.y = 0.0f; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + } + else if ( m_actionType == MHS_DEADw ) // drowned? + { + pos = m_object->RetPosition(0); + level = m_water->RetLevel()-0.5f; + if ( pos.y < level ) + { + pos.y += 4.0f*event.rTime; // back to the surface + if ( pos.y > level ) pos.y = level; + m_object->SetPosition(0, pos); + } + if ( pos.y > level ) + { + pos.y -= 10.0f*event.rTime; // down quickly + if ( pos.y < level ) pos.y = level; + m_object->SetPosition(0, pos); + } + + prog = m_progress; + if ( prog >= 1.0f ) + { + prog = 1.0f; + if ( pos.y >= level ) m_object->SetEnable(FALSE); + } + + prog *= 2.0f; + if ( prog > 1.0f ) prog = 1.0f; + + time = 100.0f; + + dir.z = -(90.0f*PI/180.0f)*prog; + dir.x = Rand()*0.3f*deadFactor; + dir.y = Rand()*0.3f*deadFactor; + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + m_object->SetInclinaison(dir); + + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + } + else if ( m_actionType == MHS_LOST ) // lost? + { + time = m_time; + if ( time < 10.0f ) time *= time/10.0f; // starts slowly + + dir.x = time*2.0f; + dir.y = sinf(m_time*0.8f)*0.8f; + dir.z = sinf(m_time*0.6f)*0.5f; + m_object->SetInclinaison(dir); + SetInclinaison(dir); + +//? dir.x = -(sinf(time*0.05f+PI*1.5f)+1.0f)*100.0f; + // original code: Min(time/30.0f) (?) changed to time/30.0f + dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance + dir.y = 0.0f; + dir.z = 0.0f; + m_object->SetLinVibration(dir); + SetLinVibration(dir); + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(0.5f, 3.7f, 0.0f); + pos.x += (Rand()-0.5f)*1.0f; + pos.y += (Rand()-0.5f)*1.0f; + pos.z += (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed.x = (Rand()-0.5f)*0.5f; + speed.y = (Rand()-0.5f)*0.5f; + speed.z = (Rand()-0.5f)*0.5f; + dim.x = 0.5f+Rand()*0.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f); + } + else if ( m_actionType == MHS_SATCOM ) // look at the SatCom? + { + SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + SetLinVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + SetInclinaison(D3DVECTOR(0.0f, 0.0f, 0.0f)); + } + else + { + if ( m_physics->RetLand() ) // on the ground? + { + time = event.rTime*8.0f; + if ( bSwim ) time *= 0.25f; + + if ( action == MH_MARCH ) // walking? + { + dir.x = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.10f; + dir.y = sinf(Mod(rTime[0]+0.6f, 1.0f)*PI*2.0f)*0.20f; + s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f; + } + else if ( action == MH_MARCHTAKE ) // takes walking? + { + dir.x = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.10f; + dir.y = sinf(Mod(rTime[0]+0.6f, 1.0f)*PI*2.0f)*0.15f; + s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f; + } + else + { + dir.x = 0.0f; + dir.y = 0.0f; + s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f; + } + + if ( s < 0.0f ) s *= 0.5f; + dir.z = -s*0.7f; + + actual = m_object->RetInclinaison(); + dir.x = Smooth(actual.x, dir.x, time); + dir.y = Smooth(actual.y, dir.y, time); + dir.z = Smooth(actual.z, dir.z, time); + if ( bOnBoard ) dir *= 0.3f; + m_object->SetInclinaison(dir); + SetInclinaison(dir); + + if ( action == MH_MARCH ) // walking? + { + p2.x = 0.0f; + p2.y = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.5f; + p2 = RotatePoint(-m_object->RetAngleY(0), p2); + dir.x = p2.x; + dir.z = p2.y; + dir.y = sinf(Mod(rTime[0]*2.0f, 1.0f)*PI*2.0f)*0.3f; + } + else if ( action == MH_MARCHTAKE ) // takes walking? + { + p2.x = 0.0f; + p2.y = sinf(Mod(rTime[0]+0.5f, 1.0f)*PI*2.0f)*0.25f; + p2 = RotatePoint(-m_object->RetAngleY(0), p2); + dir.x = p2.x; + dir.z = p2.y; + dir.y = sinf(Mod(rTime[0]*2.0f, 1.0f)*PI*2.0f)*0.05f-0.3f; + } + else + { + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = 0.0f; + } + + actual = m_object->RetLinVibration(); + dir.x = Smooth(actual.x, dir.x, time); + if ( action == MH_MARCHTAKE ) // takes walking? + { + dir.y = -hr; + } + else + { + s = Min(m_armTimeAction, 1.0f); + dir.y = Smooth(actual.y, dir.y, time)*s; + dir.y += -hr*(1.0f-s); + } + dir.z = Smooth(actual.z, dir.z, time); + if ( bOnBoard ) dir *= 0.3f; + m_object->SetLinVibration(dir); + + dir.x = 0.0f; + dir.z = 0.0f; + dir.y = 0.0f; + SetCirVibration(dir); + } + } + + // Management of the head. + if ( m_actionType == MHS_TAKE || // takes? + m_actionType == MHS_FLAG ) // takes? + { + m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f)); + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f); + m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f)); + } + else if ( m_actionType == MHS_TAKEOTHER || // takes? + m_actionType == MHS_TAKEHIGH ) // takes? + { + m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f)); + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f); + m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f)); + } + else if ( m_actionType == MHS_WIN ) // win + { + float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f); + m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor); + m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); + m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f); + } + else if ( m_actionType == MHS_LOST ) // lost? + { + float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f); + m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f); + m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f); + m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor); + } + else if ( m_object->RetDead() ) // dead? + { + } + else + { + m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f)); + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f); + m_object->SetAngleY(1, Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f)); + } + + if ( bOnBoard ) + { + m_object->SetAngleZ(1, 0.0f); + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleY(1, 0.0f); + } + + // Steps sound effects. + if ( legAction == MH_MARCH || + legAction == MH_MARCHTAKE ) + { + Sound sound[2]; + float speed, synchro, volume[2], freq[2], hard, level; + + speed = m_physics->RetLinMotionX(MO_REASPEED); + + if ( m_object->RetFret() == 0 ) + { + if ( speed > 0.0f ) synchro = 0.21f; // synchro forward + else synchro = 0.29f; // synchro backward + } + else + { + if ( speed > 0.0f ) synchro = 0.15f; // synchro forward + else synchro = 0.35f; // synchro backward + } + time = rTime[1]+synchro; + + if ( Abs(m_lastSoundMarch-time) > 0.4f && + Mod(time, 0.5f) < 0.1f ) + { + volume[0] = 0.5f; + freq[0] = 1.0f; + if ( m_object->RetFret() != 0 ) + { +//? volume[0] *= 2.0f; + freq[0] = 0.7f; + } + volume[1] = volume[0]; + freq[1] = freq[0]; + sound[0] = SOUND_CLICK; + sound[1] = SOUND_CLICK; + + pos = m_object->RetPosition(0); + + level = m_water->RetLevel(); + if ( pos.y <= level+3.0f ) // underwater? + { + sound[0] = SOUND_STEPw; + } + else + { + hard = m_terrain->RetHardness(pos); + + if ( hard >= 0.875 ) + { + sound[0] = SOUND_STEPm; // metal + } + else + { + hard /= 0.875; + sound[0] = SOUND_STEPs; // smooth + sound[1] = SOUND_STEPh; // hard + + volume[0] *= 1.0f-hard; + volume[1] *= hard; + if ( hard < 0.5f ) + { + volume[0] *= 1.0f+hard*2.0f; + volume[1] *= 1.0f+hard*2.0f; + } + else + { + volume[0] *= 3.0f-hard*2.0f; + volume[1] *= 3.0f-hard*2.0f; + } + freq[0] *= 1.0f+hard; + freq[1] *= 0.5f+hard; + } + } + + if ( sound[0] != SOUND_CLICK ) + { + m_sound->Play(sound[0], pos, volume[0], freq[0]); + } + if ( sound[1] != SOUND_CLICK ) + { + m_sound->Play(sound[1], pos, volume[1], freq[1]); + } + m_lastSoundMarch = time; + } + } + + if ( legAction == MH_SWIM ) + { + time = rTime[0]+0.5f; + + if ( Abs(m_lastSoundMarch-time) > 0.9f && + Mod(time, 1.0f) < 0.1f ) + { + m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f); + m_lastSoundMarch = time; + } + } + + m_lastSoundHhh -= event.rTime; + if ( m_lastSoundHhh <= 0.0f && + m_object->RetSelect() && + m_object->RetOption() == 0 ) // helmet? + { + m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f)); + m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Rand(); + } + + return TRUE; +} + + +// Management of the display mode when customizing the personal. + +void CMotionHuman::StartDisplayPerso() +{ + m_bDisplayPerso = TRUE; +} + +void CMotionHuman::StopDisplayPerso() +{ + m_bDisplayPerso = FALSE; +} + + diff --git a/src/object/motion/motionhuman.h b/src/object/motion/motionhuman.h new file mode 100644 index 0000000..44a0c4c --- /dev/null +++ b/src/object/motion/motionhuman.h @@ -0,0 +1,102 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionhuman.h + +#ifndef _MOTIONHUMAN_H_ +#define _MOTIONHUMAN_H_ + + +#include "motion.h" +#include "misc.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +#define MH_MARCH 0 +#define MH_MARCHTAKE 1 +#define MH_TURN 2 +#define MH_STOP 3 +#define MH_FLY 4 +#define MH_SWIM 5 +#define MH_SPEC 6 + +#define MHS_FIRE 0 +#define MHS_GUN 1 +#define MHS_TAKE 2 +#define MHS_TAKEOTHER 3 +#define MHS_TAKEHIGH 4 +#define MHS_UPRIGHT 5 +#define MHS_WIN 6 +#define MHS_LOST 7 +#define MHS_DEADg 8 +#define MHS_DEADg1 9 +#define MHS_DEADg2 10 +#define MHS_DEADg3 11 +#define MHS_DEADg4 12 +#define MHS_DEADw 13 +#define MHS_FLAG 14 +#define MHS_SATCOM 15 + + +class CMotionHuman : public CMotion +{ +public: + CMotionHuman(CInstanceManager* iMan, CObject* object); + ~CMotionHuman(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + Error SetAction(int action, float time=0.2f); + + void StartDisplayPerso(); + void StopDisplayPerso(); + +protected: + void CreatePhysics(ObjectType type); + BOOL EventFrame(const Event &event); + +protected: + int m_partiReactor; + float m_armMember; + float m_armTimeAbs; + float m_armTimeAction; + float m_armTimeSwim; + short m_armAngles[3*3*3*3*7 + 3*3*3*16]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + BOOL m_bArmStop; + float m_lastSoundMarch; + float m_lastSoundHhh; + float m_time; + float m_tired; + BOOL m_bDisplayPerso; +}; + + +#endif //_MOTIONHUMAN_H_ diff --git a/src/object/motion/motionmother.cpp b/src/object/motion/motionmother.cpp new file mode 100644 index 0000000..872ef76 --- /dev/null +++ b/src/object/motion/motionmother.cpp @@ -0,0 +1,543 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionmother.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionmother.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeMarch = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLastAction = -1; + m_specAction = -1; + m_bArmStop = FALSE; +} + +// Object's destructor. + +CMotionMother::~CMotionMother() +{ +} + + +// Removes an object. + +void CMotionMother::DeleteObject(BOOL bAll) +{ +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionMother::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 2+12+6 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + + pModFile->ReadModel("objects\\mother1.mod"); + pModFile->CreateEngineObject(rank); + + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have a obligatory collision + //with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(-2.0f, 10.0f, 0.0f), 25.0f); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\mother2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(16.0f, 3.0f, 0.0f)); + + // Creates a right-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(-5.0f, -1.0f, -12.0f)); + + // Creates a right-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates a middle-right leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(3.5f, -1.0f, -12.0f)); + + // Creates a middle-right foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates a right-front leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(10.0f, -1.0f, -10.0f)); + + // Creates a right-front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 6); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates a left-back leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(-5.0f, -1.0f, 12.0f)); + m_object->SetAngleY(8, PI); + + // Creates a left-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 8); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates a middle-left leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10, rank); + m_object->SetObjectParent(10, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10, D3DVECTOR(3.5f, -1.0f, 12.0f)); + m_object->SetAngleY(10, PI); + + // Creates a middle-left foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(11, rank); + m_object->SetObjectParent(11, 10); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(11, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates a left-front leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(12, rank); + m_object->SetObjectParent(12, 0); + pModFile->ReadModel("objects\\mother3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(12, D3DVECTOR(10.0f, -1.0f, 10.0f)); + m_object->SetAngleY(12, PI); + + // Creates a left-front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(13, rank); + m_object->SetObjectParent(13, 12); + pModFile->ReadModel("objects\\mother4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(13, D3DVECTOR(0.0f, 0.0f, -8.5f)); + + // Creates the right antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(14, rank); + m_object->SetObjectParent(14, 1); + pModFile->ReadModel("objects\\mother5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(14, D3DVECTOR(6.0f, 1.0f, -2.5f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(15, rank); + m_object->SetObjectParent(15, 14); + pModFile->ReadModel("objects\\mother6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(15, D3DVECTOR(8.0f, 0.0f, 0.0f)); + + // Creates the left antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(16, rank); + m_object->SetObjectParent(16, 1); + pModFile->ReadModel("objects\\mother5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(16, D3DVECTOR(6.0f, 1.0f, 2.5f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(17, rank); + m_object->SetObjectParent(17, 16); + pModFile->ReadModel("objects\\mother6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(17, D3DVECTOR(8.0f, 0.0f, 0.0f)); + + // Creates the right claw. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(18, rank); + m_object->SetObjectParent(18, 1); + pModFile->ReadModel("objects\\mother7.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(18, D3DVECTOR(-4.0f, -3.5f, -8.0f)); + m_object->SetZoomX(18, 1.2f); + + // Creates the left claw. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(19, rank); + m_object->SetObjectParent(19, 1); + pModFile->ReadModel("objects\\mother7.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(19, D3DVECTOR(-4.0f, -3.5f, 8.0f)); + m_object->SetZoomX(19, 1.2f); + + m_object->CreateShadowCircle(18.0f, 0.8f); + + CreatePhysics(); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physics of the object. + +void CMotionMother::CreatePhysics() +{ + Character* character; + int i; + + int member[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3 + -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3 + 0,0,0, 0,0,0, 0,0,0, // t0: unused + // on the ground: + 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3 + -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3 + 0,0,0, 0,0,0, 0,0,0, // t1: unused + // on the ground back: + 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3 + -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3 + 0,0,0, 0,0,0, 0,0,0, // t2: unused + }; + + m_physics->SetType(TYPE_ROLLING); + + character = m_object->RetCharacter(); + character->wheelFront = 10.0f; + character->wheelBack = 10.0f; + character->wheelLeft = 20.0f; + character->wheelRight = 20.0f; + character->height = 3.0f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 8.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 10.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 30.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 10.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 20.0f); + + for ( i=0 ; i<3*3*3*3 ; i++ ) + { + m_armAngles[i] = member[i]; + } +} + + +// Management of an event. + +BOOL CMotionMother::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ANGLE + int i; + + if ( event.param == 'A' ) m_armTimeIndex++; + if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0; + + if ( event.param == 'Q' ) m_armPartIndex++; + if ( m_armPartIndex >= 3 ) m_armPartIndex = 0; + + if ( event.param == 'W' ) m_armMemberIndex++; + if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0; + + i = m_armMemberIndex*3; + i += m_armPartIndex*3*3; + i += m_armTimeIndex*3*3*3; +//? i += 3*3*3*3; + + if ( event.param == 'E' ) m_armAngles[i+0] += 5; + if ( event.param == 'D' ) m_armAngles[i+0] -= 5; + if ( event.param == 'R' ) m_armAngles[i+1] += 5; + if ( event.param == 'F' ) m_armAngles[i+1] -= 5; + if ( event.param == 'T' ) m_armAngles[i+2] += 5; + if ( event.param == 'G' ) m_armAngles[i+2] -= 5; + + if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop; +#endif + } + + return TRUE; +} + +// Management of an event. + +BOOL CMotionMother::EventFrame(const Event &event) +{ + D3DVECTOR dir; + float s, a, prog; + int i, st, nd; + BOOL bStop; + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f; + a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f); + + if ( s == 0.0f && a != 0.0f ) a *= 1.5f; + + m_armTimeAbs += event.rTime; + m_armTimeMarch += (s)*event.rTime*0.05f; + m_armMember += (s+a)*event.rTime*0.05f; + + bStop = ( a == 0.0f && s == 0.0f ); // stop? + + if ( bStop ) + { + prog = Mod(m_armTimeAbs, 2.0f)/10.0f; + a = Mod(m_armMember, 1.0f); + a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly + m_armMember += a; + } + + for ( i=0 ; i<6 ; i++ ) // the six legs + { + if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f); + else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f); + if ( m_bArmStop ) + { + prog = (float)m_armTimeIndex/3.0f; + } + if ( prog < 0.33f ) // t0..t1 ? + { + prog = prog/0.33f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.67f ) // t1..t2 ? + { + prog = (prog-0.33f)/0.33f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.67f)/0.33f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + st = st*27+(i%3)*3; + nd = nd*27+(i%3)*3; + if ( i < 3 ) // right leg (1..3) ? + { + m_object->SetAngleX(2+2*i+0, Prop(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog)); + m_object->SetAngleY(2+2*i+0, Prop(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog)); + m_object->SetAngleZ(2+2*i+0, Prop(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog)); + m_object->SetAngleX(2+2*i+1, Prop(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog)); + m_object->SetAngleY(2+2*i+1, Prop(m_armAngles[st+10], m_armAngles[nd+10], prog)); + m_object->SetAngleZ(2+2*i+1, Prop(m_armAngles[st+11], m_armAngles[nd+11], prog)); + } + else // left leg (4..6) ? + { + m_object->SetAngleX(2+2*i+0, Prop( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog)); + m_object->SetAngleY(2+2*i+0, Prop(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog)); + m_object->SetAngleZ(2+2*i+0, Prop( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog)); + m_object->SetAngleX(2+2*i+1, Prop( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog)); + m_object->SetAngleY(2+2*i+1, Prop( -m_armAngles[st+10], -m_armAngles[nd+10], prog)); + m_object->SetAngleZ(2+2*i+1, Prop( -m_armAngles[st+11], -m_armAngles[nd+11], prog)); + } + } + +#if ADJUST_ANGLE + if ( m_object->RetSelect() ) + { + char s[100]; + sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex); + m_engine->SetInfoText(4, s); + } +#endif + + if ( !bStop && !m_object->RetRuin() ) + { + a = Mod(m_armTimeMarch, 1.0f); + if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1 + else a = 3.0f-4.0f*a; // 1..-1 + dir.x = sinf(a)*0.03f; + + s = Mod(m_armTimeMarch/2.0f, 1.0f); + if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1 + else s = 3.0f-4.0f*s; // 1..-1 + dir.z = sinf(s)*0.05f; + + dir.y = 0.0f; + m_object->SetInclinaison(dir); + + a = Mod(m_armMember-0.1f, 1.0f); + if ( a < 0.33f ) + { + dir.y = -(1.0f-(a/0.33f))*0.3f; + } + else if ( a < 0.67f ) + { + dir.y = 0.0f; + } + else + { + dir.y = -(a-0.67f)/0.33f*0.3f; + } + dir.x = 0.0f; + dir.z = 0.0f; + m_object->SetLinVibration(dir); + } + + m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head + m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head + m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head + + m_object->SetAngleZ(14, 0.50f); + m_object->SetAngleZ(16, 0.50f); + m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna + m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f); + m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna + m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f); + + m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw + m_object->SetAngleZ(18, -0.20f); + m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw + m_object->SetAngleZ(19, -0.20f); + + return TRUE; +} + + diff --git a/src/object/motion/motionmother.h b/src/object/motion/motionmother.h new file mode 100644 index 0000000..6e8eb32 --- /dev/null +++ b/src/object/motion/motionmother.h @@ -0,0 +1,67 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionmother.h + +#ifndef _MOTIONMOTHER_H_ +#define _MOTIONMOTHER_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +class CMotionMother : public CMotion +{ +public: + CMotionMother(CInstanceManager* iMan, CObject* object); + ~CMotionMother(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + +protected: + void CreatePhysics(); + BOOL EventFrame(const Event &event); + +protected: + float m_armMember; + float m_armTimeAbs; + float m_armTimeMarch; + float m_armTimeAction; + short m_armAngles[3*3*3*3*10]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + int m_specAction; + float m_specTime; + BOOL m_bArmStop; +}; + + +#endif //_MOTIONMOTHER_H_ diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp new file mode 100644 index 0000000..99c3d06 --- /dev/null +++ b/src/object/motion/motionspider.cpp @@ -0,0 +1,789 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionspider.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionspider.h" + + + +#define ADJUST_ANGLE FALSE // TRUE -> adjusts the angles of the members +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeMarch = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLastAction = -1; + m_bArmStop = FALSE; + m_lastParticule = 0.0f; +} + +// Object's destructor. + +CMotionSpider::~CMotionSpider() +{ +} + + +// Removes an object. + +void CMotionSpider::DeleteObject(BOOL bAll) +{ +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionSpider::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank, i, j, parent; + char name[50]; + + float table[] = + { + // x y z + 0.6f, 0.0f, 0.0f, // back leg + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + + 0.8f, 0.0f, -0.2f, // middle-back leg + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + + 1.0f, 0.0f, -0.2f, // middle-front leg + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + + 1.2f, 0.0f, 0.0f, // front leg + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + 0.0f, 0.0f, -2.0f, + }; + + if ( m_engine->RetRestCreate() < 3+32+2 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist + pModFile->CreateEngineObject(rank); + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have a obligatory collision + // with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(-0.5f, 1.0f, 0.0f), 4.0f); + + // Creates the abdomen. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\spider1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(1.0f, 0.0f, 0.0f)); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\spider2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(1.0f, 0.0f, 0.0f)); + + // Creates legs. + for ( i=0 ; i<4 ; i++ ) + { + for ( j=0 ; j<4 ; j++ ) + { + sprintf(name, "objects\\spider%d.mod", j+3); // 3..6 + + // Creates the right leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3+i*4+j, rank); + if ( j == 0 ) parent = 0; + else parent = 3+i*4+j-1; + m_object->SetObjectParent(3+i*4+j, parent); + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + pos.x = table[i*12+j*3+0]; + pos.y = table[i*12+j*3+1]; + pos.z = table[i*12+j*3+2]; + m_object->SetPosition(3+i*4+j, pos); + + // Creates the left leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(19+i*4+j, rank); + if ( j == 0 ) parent = 0; + else parent = 19+i*4+j-1; + m_object->SetObjectParent(19+i*4+j, parent); + pModFile->ReadModel(name); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + pos.x = table[i*12+j*3+0]; + pos.y = table[i*12+j*3+1]; + pos.z = -table[i*12+j*3+2]; + m_object->SetPosition(19+i*4+j, pos); + } + } + + // Creates the right mandible. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(35, rank); + m_object->SetObjectParent(35, 1); + pModFile->ReadModel("objects\\spider7.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(35, D3DVECTOR(0.0f, 0.0f, -0.3f)); + + // Creates the left mandible. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(36, rank); + m_object->SetObjectParent(36, 1); + pModFile->ReadModel("objects\\spider7.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(36, D3DVECTOR(0.0f, 0.0f, 0.3f)); + + m_object->CreateShadowCircle(4.0f, 0.5f); + + CreatePhysics(); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physics of the object. + +void CMotionSpider::CreatePhysics() +{ + Character* character; + int i; + + int member_march[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air: + 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4 + -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4 + -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4 + 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4 + // on the ground: + 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4 + -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4 + -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4 + // on the ground back: + 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4 + -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4 + -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4 + }; + + int member_stop[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air: + 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4 + -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4 + -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4 + // on the ground: + 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4 + -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4 + -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4 + // on the ground back: + 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4 + -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4 + -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4 + -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4 + }; + + int member_spec[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning: + 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4 + -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4 + -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4 + // destroyed: + 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4 + -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4 + -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4 + // explodes: + 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4 + -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4 + -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4 + // back1 : + 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4 + -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4 + -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4 + // back2 : + 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4 + -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4 + -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4 + -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4 + // back3 : + 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4 + -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4 + -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4 + -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4 + }; + + m_physics->SetType(TYPE_ROLLING); + + character = m_object->RetCharacter(); + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 6.0f; + character->wheelRight = 6.0f; + character->height = 0.6f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 12.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 15.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 20.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 40.0f); + + for ( i=0 ; i<3*4*4*3 ; i++ ) + { + m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i]; + } + for ( i=0 ; i<3*4*4*3 ; i++ ) + { + m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i]; + } + for ( i=0 ; i<3*4*4*6 ; i++ ) + { + m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i]; + } +} + + +// Management of an event. + +BOOL CMotionSpider::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ANGLE + int i; + + if ( event.param == 'A' ) m_armTimeIndex++; + if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0; + + if ( event.param == 'Q' ) m_armPartIndex++; + if ( m_armPartIndex >= 4 ) m_armPartIndex = 0; + + if ( event.param == 'W' ) m_armMemberIndex++; + if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0; + + i = m_armMemberIndex*3; + i += m_armPartIndex*3*4; + i += m_armTimeIndex*3*4*4; + + if ( event.param == 'E' ) m_armAngles[i+0] += 5; + if ( event.param == 'D' ) m_armAngles[i+0] -= 5; + if ( event.param == 'R' ) m_armAngles[i+1] += 5; + if ( event.param == 'F' ) m_armAngles[i+1] -= 5; + if ( event.param == 'T' ) m_armAngles[i+2] += 5; + if ( event.param == 'G' ) m_armAngles[i+2] -= 5; + if ( event.param == 'Z' ) m_armAngles[i+3] += 5; + if ( event.param == 'H' ) m_armAngles[i+3] -= 5; + + if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop; +#endif + } + + return TRUE; +} + +// Calculates a value (radians) proportional between a and b (degrees). + +inline float Propf(float a, float b, float p) +{ + float aa, bb; + + aa = a*PI/180.0f; + bb = b*PI/180.0f; + + return aa+p*(bb-aa); +} + +// Management of an event. + +BOOL CMotionSpider::EventFrame(const Event &event) +{ + D3DVECTOR dir, pos, speed; + FPOINT dim; + float s, a, prog, time; + float tSt[12], tNd[12]; + int i, ii, st, nd, action; + BOOL bStop; + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f; + a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f); + + if ( s == 0.0f && a != 0.0f ) a *= 1.5f; + + m_armTimeAbs += event.rTime; + m_armTimeAction += event.rTime; + m_armTimeMarch += (s)*event.rTime*0.15f; + m_armMember += (s+a)*event.rTime*0.15f; + + bStop = ( a == 0.0f && s == 0.0f ); // stop? + + action = MS_MARCH; // waslking + if ( s == 0.0f && a == 0.0f ) + { + action = MS_STOP; // stop + } + + if ( bStop ) + { + prog = Mod(m_armTimeAbs, 2.0f)/10.0f; + a = Mod(m_armMember, 1.0f); + a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly + m_armMember += a; + } + + if ( m_object->RetRuin() ) // destroyed? + { + m_actionType = MSS_RUIN; + } + if ( m_object->RetBurn() ) // burning? + { + if ( m_object->RetFixed() ) + { + m_actionType = MSS_BURN; + } + else + { + m_actionType = -1; + } + } + + for ( i=0 ; i<8 ; i++ ) // the 8 legs + { + if ( m_actionType != -1 ) // special action in progress? + { + st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3; + nd = st; + time = event.rTime*m_actionTime; + m_armTimeAction = 0.0f; + } + else + { +//? if ( i < 4 ) prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f); +//? else prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f); + if ( i < 4 ) prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f); + else prog = Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f); + if ( m_bArmStop ) + { + prog = (float)m_armTimeIndex/3.0f; + action = MS_MARCH; + } + if ( prog < 0.33f ) // t0..t1 ? + { + prog = prog/0.33f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.67f ) // t1..t2 ? + { + prog = (prog-0.33f)/0.33f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.67f)/0.33f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + st = 3*4*4*3*action + st*3*4*4 + (i%4)*3; + nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3; + + // Less and less soft ... +//? time = event.rTime*(2.0f+Min(m_armTimeAction*20.0f, 40.0f)); + time = event.rTime*10.0f; + } + + tSt[ 0] = m_armAngles[st+ 0]; // x + tSt[ 1] = m_armAngles[st+ 1]; // y + tSt[ 2] = m_armAngles[st+ 2]; // z + tSt[ 3] = m_armAngles[st+12]; // x + tSt[ 4] = m_armAngles[st+13]; // y + tSt[ 5] = m_armAngles[st+14]; // z + tSt[ 6] = m_armAngles[st+24]; // x + tSt[ 7] = m_armAngles[st+25]; // y + tSt[ 8] = m_armAngles[st+26]; // z + tSt[ 9] = m_armAngles[st+36]; // x + tSt[10] = m_armAngles[st+37]; // y + tSt[11] = m_armAngles[st+38]; // z + + tNd[ 0] = m_armAngles[nd+ 0]; // x + tNd[ 1] = m_armAngles[nd+ 1]; // y + tNd[ 2] = m_armAngles[nd+ 2]; // z + tNd[ 3] = m_armAngles[nd+12]; // x + tNd[ 4] = m_armAngles[nd+13]; // y + tNd[ 5] = m_armAngles[nd+14]; // z + tNd[ 6] = m_armAngles[nd+24]; // x + tNd[ 7] = m_armAngles[nd+25]; // y + tNd[ 8] = m_armAngles[nd+26]; // z + tNd[ 9] = m_armAngles[nd+36]; // z + tNd[10] = m_armAngles[nd+37]; // z + tNd[11] = m_armAngles[nd+38]; // z + + if ( m_actionType == MSS_BACK2 ) // on the back? + { + for ( ii=0 ; ii<12 ; ii++ ) + { + tSt[ii] += Rand()*20.0f; + tNd[ii] = tSt[ii]; + } +//? time = 100.0f; + time = event.rTime*10.0f; + } + + if ( i < 4 ) // right leg (1..4) ? + { + m_object->SetAngleX(3+4*i+0, Smooth(m_object->RetAngleX(3+4*i+0), Propf(tSt[ 0], tNd[ 0], prog), time)); + m_object->SetAngleY(3+4*i+0, Smooth(m_object->RetAngleY(3+4*i+0), Propf(tSt[ 1], tNd[ 1], prog), time)); + m_object->SetAngleZ(3+4*i+0, Smooth(m_object->RetAngleZ(3+4*i+0), Propf(tSt[ 2], tNd[ 2], prog), time)); + m_object->SetAngleX(3+4*i+1, Smooth(m_object->RetAngleX(3+4*i+1), Propf(tSt[ 3], tNd[ 3], prog), time)); + m_object->SetAngleY(3+4*i+1, Smooth(m_object->RetAngleY(3+4*i+1), Propf(tSt[ 4], tNd[ 4], prog), time)); + m_object->SetAngleZ(3+4*i+1, Smooth(m_object->RetAngleZ(3+4*i+1), Propf(tSt[ 5], tNd[ 5], prog), time)); + m_object->SetAngleX(3+4*i+2, Smooth(m_object->RetAngleX(3+4*i+2), Propf(tSt[ 6], tNd[ 6], prog), time)); + m_object->SetAngleY(3+4*i+2, Smooth(m_object->RetAngleY(3+4*i+2), Propf(tSt[ 7], tNd[ 7], prog), time)); + m_object->SetAngleZ(3+4*i+2, Smooth(m_object->RetAngleZ(3+4*i+2), Propf(tSt[ 8], tNd[ 8], prog), time)); + m_object->SetAngleX(3+4*i+3, Smooth(m_object->RetAngleX(3+4*i+3), Propf(tSt[ 9], tNd[ 9], prog), time)); + m_object->SetAngleY(3+4*i+3, Smooth(m_object->RetAngleY(3+4*i+3), Propf(tSt[10], tNd[10], prog), time)); + m_object->SetAngleZ(3+4*i+3, Smooth(m_object->RetAngleZ(3+4*i+3), Propf(tSt[11], tNd[11], prog), time)); + } + else // left leg (5..8) ? + { + m_object->SetAngleX(3+4*i+0, Smooth(m_object->RetAngleX(3+4*i+0), Propf(-tSt[ 0], -tNd[ 0], prog), time)); + m_object->SetAngleY(3+4*i+0, Smooth(m_object->RetAngleY(3+4*i+0), Propf(-tSt[ 1], -tNd[ 1], prog), time)); + m_object->SetAngleZ(3+4*i+0, Smooth(m_object->RetAngleZ(3+4*i+0), Propf( tSt[ 2], tNd[ 2], prog), time)); + m_object->SetAngleX(3+4*i+1, Smooth(m_object->RetAngleX(3+4*i+1), Propf(-tSt[ 3], -tNd[ 3], prog), time)); + m_object->SetAngleY(3+4*i+1, Smooth(m_object->RetAngleY(3+4*i+1), Propf(-tSt[ 4], -tNd[ 4], prog), time)); + m_object->SetAngleZ(3+4*i+1, Smooth(m_object->RetAngleZ(3+4*i+1), Propf( tSt[ 5], tNd[ 5], prog), time)); + m_object->SetAngleX(3+4*i+2, Smooth(m_object->RetAngleX(3+4*i+2), Propf(-tSt[ 6], -tNd[ 6], prog), time)); + m_object->SetAngleY(3+4*i+2, Smooth(m_object->RetAngleY(3+4*i+2), Propf(-tSt[ 7], -tNd[ 7], prog), time)); + m_object->SetAngleZ(3+4*i+2, Smooth(m_object->RetAngleZ(3+4*i+2), Propf( tSt[ 8], tNd[ 8], prog), time)); + m_object->SetAngleX(3+4*i+3, Smooth(m_object->RetAngleX(3+4*i+3), Propf(-tSt[ 9], -tNd[ 9], prog), time)); + m_object->SetAngleY(3+4*i+3, Smooth(m_object->RetAngleY(3+4*i+3), Propf(-tSt[10], -tNd[10], prog), time)); + m_object->SetAngleZ(3+4*i+3, Smooth(m_object->RetAngleZ(3+4*i+3), Propf( tSt[11], tNd[11], prog), time)); + } + } + +#if ADJUST_ANGLE + if ( m_object->RetSelect() ) + { + char s[100]; + sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex); + m_engine->SetInfoText(4, s); + } +#endif + + if ( m_actionType == MSS_BURN ) // burning? + { + dir = D3DVECTOR(PI, 0.0f, 0.0f); + SetCirVibration(dir); + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + SetInclinaison(dir); + + time = event.rTime*1.0f; + m_object->SetAngleZ(1, Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head + } + else if ( m_actionType == MSS_RUIN ) // destroyed? + { + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + SetCirVibration(dir); + SetInclinaison(dir); + } + else if ( m_actionType == MSS_EXPLO ) // exploded? + { + m_object->SetZoomY(1, 1.0f+m_progress); + m_object->SetZoomZ(1, 1.0f+m_progress); + m_object->SetZoomX(1, 1.0f+m_progress/2.0f); + + dir.x = (Rand()-0.5f)*0.1f*m_progress; + dir.y = (Rand()-0.5f)*0.1f*m_progress; + dir.z = (Rand()-0.5f)*0.1f*m_progress; + m_object->SetCirVibration(dir); + } + else if ( m_actionType == MSS_BACK1 ) // turns on the back? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress < 0.5f ) + { + dir.x = 0.0f; + dir.y = powf(m_progress/0.5f, 2.0f)*12.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + else + { + dir.x = 0.0f; + dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + dir.x = m_progress*PI; + dir.y = 0.0f; + dir.z = 0.0f; + SetCirVibration(dir); + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + if ( m_progress >= 1.0f ) + { + SetAction(MSS_BACK2, 55.0f+Rand()*10.0f); + } + } + else if ( m_actionType == MSS_BACK2 ) // moves on the back? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + if ( rand()%10 == 0 ) + { + pos = m_object->RetPosition(0); + pos.x += (Rand()-0.5f)*8.0f; + pos.z += (Rand()-0.5f)*8.0f; + pos.y -= 1.0f; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = (Rand()-0.5f)*2.0f; + speed.y = Rand()*2.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + } + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+ + sinf(m_armTimeAbs* 6.0f)*0.20f+ + sinf(m_armTimeAbs*10.0f)*0.20f+ + sinf(m_armTimeAbs*17.0f)*0.30f+PI; + dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+ + sinf(m_armTimeAbs* 5.0f)*0.02f+ + sinf(m_armTimeAbs*11.0f)*0.02f+ + sinf(m_armTimeAbs*18.0f)*0.03f; + dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+ + sinf(m_armTimeAbs* 7.0f)*0.02f+ + sinf(m_armTimeAbs*13.0f)*0.02f+ + sinf(m_armTimeAbs*15.0f)*0.03f; + SetCirVibration(dir); + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail + m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head + m_object->SetAngleZ(1, 0.4f); // tail + m_object->SetAngleZ(2, 0.0f); // head + + if ( m_progress >= 1.0f ) + { + SetAction(MSS_BACK3, 0.4f); + } + } + else if ( m_actionType == MSS_BACK3 ) // recovers on the legs? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs ) + { + m_lastParticule = m_armTimeAbs; + + pos = m_object->RetPosition(0); + speed.x = (Rand()-0.5f)*10.0f; + speed.z = (Rand()-0.5f)*10.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*3.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + if ( m_progress < 0.5f ) + { + dir.x = 0.0f; + dir.y = powf(m_progress/0.5f, 2.0f)*5.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + else + { + dir.x = 0.0f; + dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f; + dir.z = 0.0f; + SetLinVibration(dir); + } + dir.x = (1.0f-m_progress)*PI; + dir.y = 0.0f; + dir.z = 0.0f; + SetCirVibration(dir); + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + + if ( m_progress >= 1.0f ) + { + SetAction(-1); + m_object->SetFixed(FALSE); // moving again + } + } + else + { + if ( bStop ) + { + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetInclinaison(dir); + } + else + { + a = Mod(m_armMember, 1.0f); + if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1 + else a = 3.0f-4.0f*a; // 1..-1 + dir.x = sinf(a)*0.05f; + + s = Mod(m_armMember/2.0f, 1.0f); + if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1 + else s = 3.0f-4.0f*s; // 1..-1 + dir.z = sinf(s)*0.1f; + + dir.y = 0.0f; + SetInclinaison(dir); + } + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + SetLinVibration(dir); + SetCirVibration(dir); + + m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail + m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f); + m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f); + m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f); + + m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head + m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f); + m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f); + + m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible + m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible + } + + return TRUE; +} + + diff --git a/src/object/motion/motionspider.h b/src/object/motion/motionspider.h new file mode 100644 index 0000000..294daf3 --- /dev/null +++ b/src/object/motion/motionspider.h @@ -0,0 +1,78 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionspider.h + +#ifndef _MOTIONSPIDER_H_ +#define _MOTIONSPIDER_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +#define MS_MARCH 0 +#define MS_STOP 1 +#define MS_SPEC 2 + +#define MSS_BURN 0 +#define MSS_RUIN 1 +#define MSS_EXPLO 2 +#define MSS_BACK1 3 +#define MSS_BACK2 4 +#define MSS_BACK3 5 + + +class CMotionSpider : public CMotion +{ +public: + CMotionSpider(CInstanceManager* iMan, CObject* object); + ~CMotionSpider(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + +protected: + void CreatePhysics(); + BOOL EventFrame(const Event &event); + +protected: + float m_armMember; + float m_armTimeAbs; + float m_armTimeMarch; + float m_armTimeAction; + short m_armAngles[3*4*4*3*3 + 3*4*4*6]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + BOOL m_bArmStop; + float m_lastParticule; +}; + + +#endif //_MOTIONSPIDER_H_ diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp new file mode 100644 index 0000000..afd5779 --- /dev/null +++ b/src/object/motion/motiontoto.cpp @@ -0,0 +1,886 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motiontoto.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "modfile.h" +#include "robotmain.h" +#include "sound.h" +#include "motion.h" +#include "motiontoto.h" + + + +#define START_TIME 1000.0f // beginning of the relative time + + + +// Object's constructor. + +CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_time = 0.0f; + m_bDisplayInfo = FALSE; + m_bQuickPos = FALSE; + m_bStartAction = FALSE; + m_speedAction = 20.0f; + m_soundChannel = -1; + m_clownRadius = 0.0f; + m_clownDelay = 0.0f; + m_clownTime = 0.0f; + m_blinkTime = 0.0f; + m_blinkProgress = -1.0f; + m_lastMotorParticule = 0.0f; + m_type = OBJECT_NULL; + m_mousePos = FPOINT(0.0f, 0.0f); +} + +// Object's destructor. + +CMotionToto::~CMotionToto() +{ +} + + +// Removes an object. + +void CMotionToto::DeleteObject(BOOL bAll) +{ + if ( m_soundChannel != -1 ) + { + m_sound->Stop(m_soundChannel); + m_soundChannel = -1; + } +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionToto::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 10 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + pModFile->ReadModel("objects\\toto1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // Creates mouth. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\toto2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(1.00f, 0.17f, 0.00f)); + + // Creates the left eye. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\toto3.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(0.85f, 1.04f, 0.25f)); + m_object->SetAngleY(2, -20.0f*PI/180.0f); + + // Creates the right eye. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 0); + pModFile->ReadModel("objects\\toto3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(0.85f, 1.04f, -0.25f)); + m_object->SetAngleY(3, 20.0f*PI/180.0f); + + // Creates left antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 0); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(0.0f, 1.9f, 0.3f)); + m_object->SetAngleX(4, 30.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(0.0f, 0.67f, 0.0f)); + m_object->SetAngleX(5, 30.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 5); + pModFile->ReadModel("objects\\toto5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, 0.70f, 0.0f)); + m_object->SetAngleX(6, 30.0f*PI/180.0f); + + // Creates right antenna. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 1.9f, -0.3f)); + m_object->SetAngleX(7, -30.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 7); + pModFile->ReadModel("objects\\toto4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(0.0f, 0.67f, 0.0f)); + m_object->SetAngleX(8, -30.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 8); + pModFile->ReadModel("objects\\toto5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(0.0f, 0.70f, 0.0f)); + m_object->SetAngleX(9, -30.0f*PI/180.0f); + + m_object->SetZoom(0, 0.5f); // is little + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + + +// Beginning of the display of informations, with foo in the left margin. + +void CMotionToto::StartDisplayInfo() +{ +return; +//? + m_bDisplayInfo = TRUE; + + m_actionType = -1; + m_actionTime = 0.0f; + m_progress = 0.0f; + + m_object->SetAngleY(0, 0.0f); + m_mousePos = FPOINT(0.5f, 0.5f); +} + +// End of the display of informations. + +void CMotionToto::StopDisplayInfo() +{ + m_bDisplayInfo = FALSE; + m_bQuickPos = TRUE; +} + +// Gives the position of the mouse. + +void CMotionToto::SetMousePos(FPOINT pos) +{ + m_mousePos = pos; +} + + +// Management of an event. + +BOOL CMotionToto::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + return TRUE; +} + +// Management of an event. + +BOOL CMotionToto::EventFrame(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR eye, lookat, dir, perp, nPos, aPos, pos, speed; + D3DVECTOR vibLin, vibCir, dirSpeed, aAntenna; + FPOINT dim; + POINT wDim; + ParticuleType type; + float progress, focus, distance, shift, verti, level, zoom; + float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed; + int sheet, i, r; + BOOL bHidden; + + if ( m_engine->RetPause() && + !m_main->RetInfoLock() ) return TRUE; + + if ( m_bDisplayInfo ) // "looks" mouse? + { + bHidden = FALSE; + } + else + { + bHidden = FALSE; + + if ( m_main->RetMovieLock() ) // current movie? + { + bHidden = TRUE; + } + if ( !m_engine->RetTotoMode() ) + { + if ( !m_main->RetEditLock() ) // current edition? + { + bHidden = TRUE; + } + } + } + + if ( bHidden ) + { + nPos = m_object->RetPosition(0); + m_terrain->MoveOnFloor(nPos, TRUE); + nPos.y -= 100.0f; // hidden under the ground! + m_object->SetPosition(0, nPos); + return TRUE; + } + + m_time += event.rTime; + m_blinkTime -= event.rTime; + + progress = 0.0f; + if ( m_actionType != -1 ) // current action? + { + if ( m_progress < 0.15f ) + { + progress = m_progress/0.15f; + } + else if ( m_progress < 0.85f ) + { + progress = 1.0f; + } + else + { + progress = (1.0f-m_progress)/0.15f; + } + } + + if ( m_progress >= 1.0f ) + { + m_actionType = -1; // action ended + m_actionTime = 0.0f; + m_progress = 0.0f; + + m_clownTime = 0.0f; + m_clownDelay = 0.0f; + } + + focus = m_engine->RetFocus(); + eye = m_engine->RetEyePt(); + lookat = m_engine->RetLookatPt(); + + vibLin = D3DVECTOR(0.0f, 0.0f, 0.0f); + vibCir = D3DVECTOR(0.0f, 0.0f, 0.0f); + aAntenna = D3DVECTOR(0.0f, 0.0f, 0.0f); + aAntenna.x += 30.0f*PI/180.0f; + + // Calculates the new position. + if ( m_bDisplayInfo ) + { + wDim = m_engine->RetDim(); + nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f); + nPos.y = -0.5f; + nPos.z = 7.0f; // in the left margin + + linSpeed = 0.0f; + } + else + { +#if 0 + distance = 30.0f-progress*24.5f; // remoteness + shift = 18.0f-progress*15.4f; // shift is left + verti = 10.0f-progress* 9.6f; // shift at the top +#else + distance = 30.0f-progress*18.0f; // remoteness + shift = 18.0f-progress*11.0f; // shift is left + verti = 10.0f-progress* 8.0f; // shift at the top +#endif + + if ( m_actionType == -1 && + (m_type == OBJECT_HUMAN || + m_type == OBJECT_TECH || + m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEws || + m_type == OBJECT_MOBILEts || + m_type == OBJECT_MOBILEfs || + m_type == OBJECT_MOBILEis || + m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILEdr ) ) // vehicle? + { + m_clownTime += event.rTime; + if ( m_clownTime >= m_clownDelay ) + { + if ( rand()%10 < 2 ) + { + m_clownRadius = 2.0f+Rand()*10.0f; +//? m_clownDelay = m_clownRadius/(2.0f+Rand()*2.0f); + m_clownDelay = 1.5f+Rand()*1.0f; + } + else + { + m_clownRadius = 0.0f; + m_clownDelay = 2.0f+Rand()*2.0f; + } + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) // underwater? + { + m_clownRadius /= 1.5f; + m_clownDelay *= 2.0f; + } + m_clownTime = 0.0f; + } + else + { + distance -= m_clownRadius*sinf(m_clownTime*PI*2.0f/m_clownDelay); + shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*PI*2.0f/m_clownDelay); + } + + verti += (18.0f-shift)*0.2f; + } + + distance /= focus; +//? shift *= focus; + verti /= focus; + + dir = Normalize(lookat-eye); + nPos = eye + dir*distance; + + perp.x = -dir.z; + perp.y = dir.y; + perp.z = dir.x; + nPos = nPos + perp*shift; + + nPos.y += verti; + + if ( m_bQuickPos ) // immediately in place? + { + m_bQuickPos = FALSE; + linSpeed = 0.0f; + } + else + { + aPos = m_object->RetPosition(0); + if ( m_actionType == -1 ) + { + level = 4.0f; + } + else + { + if ( m_bStartAction ) + { + m_bStartAction = FALSE; + m_speedAction = Length(nPos, aPos)/15.0f; + if ( m_speedAction < 20.0f ) m_speedAction = 20.0f; + } + level = m_speedAction; + } + if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime; + nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos + + linSpeed = Length2d(nPos, aPos)/event.rTime; + dirSpeed = (nPos-aPos)/event.rTime; + nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast + } + } + + // Calculate the new angle. + nAngle = NormAngle(RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f); + if ( linSpeed == 0.0f || m_actionType != -1 ) + { + mAngle = nAngle; + } + else + { + mAngle = NormAngle(RotateAngle(dirSpeed.x, -dirSpeed.z)); + } + level = Min(linSpeed*0.1f, 1.0f); + nAngle = nAngle*(1.0f-level) + mAngle*level; + aAngle = NormAngle(m_object->RetAngleY(0)); + + if ( nAngle < aAngle ) + { + if ( nAngle+PI*2.0f-aAngle < aAngle-nAngle ) nAngle += PI*2.0f; + } + else + { + if ( aAngle+PI*2.0f-nAngle < nAngle-aAngle ) aAngle += PI*2.0f; + } + nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f; + + // Leans quotes if running. + cirSpeed = (aAngle-nAngle)/event.rTime; + angle = cirSpeed*0.3f*(1.0f-progress); + if ( angle > 0.7f ) angle = 0.7f; + if ( angle < -0.7f ) angle = -0.7f; + vibCir.x += angle*1.5f; + aAntenna.x += Abs(angle)*0.8f; // deviates + + // Leans forward so quickly advance. + angle = linSpeed*0.10f*(1.0f-progress); + if ( angle > 1.0f ) angle = 1.0f; + vibCir.z -= angle/2.0f; // leans forward + aAntenna.z -= angle; // leans forward + + // Calculates the residual motion. +#if 1 + vibLin.y += (sinf(m_time*2.00f)*0.5f+ + sinf(m_time*2.11f)*0.2f)*(1.0f-progress); + + vibCir.z += sinf(m_time*PI* 2.01f)*(PI/ 75.0f)+ + sinf(m_time*PI* 2.51f)*(PI/100.0f)+ + sinf(m_time*PI*19.01f)*(PI/200.0f); + + vibCir.x += sinf(m_time*PI* 2.03f)*(PI/ 75.0f)+ + sinf(m_time*PI* 2.52f)*(PI/100.0f)+ + sinf(m_time*PI*19.53f)*(PI/200.0f); + + vibCir.y += (sinf(m_time*PI* 1.07f)*(PI/ 10.0f)+ + sinf(m_time*PI* 1.19f)*(PI/ 17.0f)+ + sinf(m_time*PI* 1.57f)*(PI/ 31.0f))*(1.0f-progress); +#endif + + // Calculates the animations in action. + if ( m_actionType == MT_ERROR ) // no-no? + { + vibCir.y += progress*sinf(m_progress*PI*11.0f)*1.0f; + vibCir.z -= progress*0.5f; // leans forward + + aAntenna.x -= progress*0.4f; // narrows + aAntenna.z += progress*1.0f; // leaning back + } + + if ( m_actionType == MT_WARNING ) // warning? + { + vibCir.x += progress*sinf(m_progress*PI*17.0f)*0.5f; + + aAntenna.x += progress*sinf(m_progress*PI*17.0f)*0.5f; // deviates + aAntenna.z += progress*cosf(m_progress*PI*17.0f)*0.5f; // turns + } + + if ( m_actionType == MT_INFO ) // yes-yes? + { + vibCir.z += progress*sinf(m_progress*PI*19.0f)*0.7f; + + aAntenna.x -= progress*0.2f; // narrows + aAntenna.z -= progress*cosf(m_progress*PI*19.0f)*0.9f; // turns + } + + if ( m_actionType == MT_MESSAGE ) // message? + { + vibCir.x += progress*sinf(m_progress*PI*15.0f)*0.3f; + vibCir.z += progress*cosf(m_progress*PI*15.0f)*0.3f; + + aAntenna.x -= progress*0.4f; // narrows + aAntenna.z -= progress*cosf(m_progress*PI*19.0f)*0.8f; + } + + // Initialize the object. + if ( m_bDisplayInfo ) // "looks" mouse? + { + if ( m_mousePos.x < 0.15f ) + { + progress = 1.0f-m_mousePos.x/0.15f; + vibCir.y += progress*PI/2.0f; + } + else + { + progress = (m_mousePos.x-0.15f)/0.85f; + vibCir.y -= progress*PI/3.0f; + } + + angle = RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f); + if ( angle < PI ) + { + if ( angle > PI*0.5f ) angle = PI-angle; + if ( angle > PI*0.3f ) angle = PI*0.3f; + vibCir.z += angle; + } + else + { + angle = PI*2.0f-angle; + if ( angle > PI*0.5f ) angle = PI-angle; + if ( angle > PI*0.3f ) angle = PI*0.3f; + vibCir.z -= angle; + } + } + else + { + nPos.y += vibLin.y; + level = m_terrain->RetFloorLevel(nPos); + if ( nPos.y < level+2.0f ) + { + nPos.y = level+2.0f; // just above the ground + } + nPos.y -= vibLin.y; + } + m_object->SetPosition(0, nPos); + m_object->SetAngleY(0, nAngle); + + SetLinVibration(vibLin); + SetCirVibration(vibCir); + + // Calculates the residual movement of the antennas. + pos = aAntenna*0.40f; + pos.x += sinf(m_time*PI*2.07f)*(PI/50.0f)+ + sinf(m_time*PI*2.59f)*(PI/70.0f)+ + sinf(m_time*PI*2.67f)*(PI/90.0f); + + pos.y += sinf(m_time*PI*2.22f)*(PI/50.0f)+ + sinf(m_time*PI*2.36f)*(PI/70.0f)+ + sinf(m_time*PI*3.01f)*(PI/90.0f); + + pos.z += sinf(m_time*PI*2.11f)*(PI/50.0f)+ + sinf(m_time*PI*2.83f)*(PI/70.0f)+ + sinf(m_time*PI*3.09f)*(PI/90.0f); + + m_object->SetAngle(4, pos); // left antenna + m_object->SetAngle(5, pos); // left antenna + m_object->SetAngle(6, pos); // left antenna + + pos = aAntenna*0.40f; + pos.x = -pos.x; + pos.x += sinf(m_time*PI*2.33f)*(PI/50.0f)+ + sinf(m_time*PI*2.19f)*(PI/70.0f)+ + sinf(m_time*PI*2.07f)*(PI/90.0f); + + pos.y += sinf(m_time*PI*2.44f)*(PI/50.0f)+ + sinf(m_time*PI*2.77f)*(PI/70.0f)+ + sinf(m_time*PI*3.22f)*(PI/90.0f); + + pos.z += sinf(m_time*PI*2.05f)*(PI/50.0f)+ + sinf(m_time*PI*2.38f)*(PI/70.0f)+ + sinf(m_time*PI*2.79f)*(PI/90.0f); + + m_object->SetAngle(7, pos); // right antenna + m_object->SetAngle(8, pos); // right antenna + m_object->SetAngle(9, pos); // right antenna + + // Movement of the mouth. + if ( m_actionType == MT_ERROR ) // no-no? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f); + m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f)); + m_object->SetZoomZ(1, 1.0f); + } + else if ( m_actionType == MT_WARNING ) // warning? + { + m_object->SetAngleX(1, 15.0f*PI/180.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 1.0f); + } + else if ( m_actionType == MT_INFO ) // yes-yes? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f); + } + else if ( m_actionType == MT_MESSAGE ) // message? + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f); + } + else + { + m_object->SetAngleX(1, 0.0f); + m_object->SetAngleZ(1, 0.0f); + m_object->SetZoomY(1, 1.0f); + m_object->SetZoomZ(1, 1.0f); + } + + // Eye blinking management. + if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f ) + { + m_blinkProgress = 0.0f; + } + + if ( m_blinkProgress >= 0.0f ) + { + m_blinkProgress += event.rTime*3.2f; + + if ( m_blinkProgress < 1.0f ) + { + if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f; + else zoom = 2.0f-m_blinkProgress/0.5f; + m_object->SetZoomY(2, 1.0f-zoom*0.9f); + m_object->SetZoomY(3, 1.0f-zoom*0.9f); + } + else + { + m_blinkProgress = -1.0f; + m_blinkTime = 0.1f+Rand()*4.0f; + m_object->SetZoomY(2, 1.0f); + m_object->SetZoomY(3, 1.0f); + } + } + + if ( m_actionType == MT_ERROR ) // no-no? + { + m_object->SetAngleX(2, -30.0f*PI/180.0f); + m_object->SetAngleX(3, 30.0f*PI/180.0f); + } + else if ( m_actionType == MT_WARNING ) // warning? + { + m_object->SetAngleX(2, -15.0f*PI/180.0f); + m_object->SetAngleX(3, 15.0f*PI/180.0f); + } + else if ( m_actionType == MT_INFO ) // yes-yes? + { + m_object->SetAngleX(2, 40.0f*PI/180.0f); + m_object->SetAngleX(3, -40.0f*PI/180.0f); + } + else if ( m_actionType == MT_MESSAGE ) // message? + { + m_object->SetAngleX(2, 20.0f*PI/180.0f); + m_object->SetAngleX(3, -20.0f*PI/180.0f); + } + else + { + m_object->SetAngleX(2, 0.0f); + m_object->SetAngleX(3, 0.0f); + } + + mat = m_object->RetWorldMatrix(0); // must be done every time! + + // Generates particles. + if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) ) + { + m_lastMotorParticule = m_time; + + if ( m_bDisplayInfo ) sheet = SH_FRONT; + else sheet = SH_WORLD; + + pos = m_object->RetPosition(0); + if ( !m_bDisplayInfo && + pos.y < m_water->RetLevel() ) // underwater? + { + float t = Mod(m_time, 3.5f); + if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe? + { + pos = D3DVECTOR(1.0f, 0.2f, 0.0f); + pos.z += (Rand()-0.5f)*0.5f; + + speed = pos; + speed.y += 5.0f+Rand()*5.0f; + speed.x += Rand()*2.0f; + speed.z += (Rand()-0.5f)*2.0f; + + pos = Transform(*mat, pos); + speed = Transform(*mat, speed)-pos; + + dim.x = 0.12f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f); + } + } + else // out of water? + { + pos = D3DVECTOR(0.0f, -0.5f, 0.0f); + pos.z += (Rand()-0.5f)*0.5f; + + speed = pos; + speed.y -= (1.5f+Rand()*1.5f) + vibLin.y; + speed.x += (Rand()-0.5f)*2.0f; + speed.z += (Rand()-0.5f)*2.0f; + +// mat = m_object->RetWorldMatrix(0); + pos = Transform(*mat, pos); + speed = Transform(*mat, speed)-pos; + + dim.x = (Rand()*0.4f+0.4f)*(1.0f+Min(linSpeed*0.1f, 5.0f)); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Rand()*1.0f, 0.0f, 1.0f, sheet); + } + + if ( m_actionType != -1 && // current action? + m_progress <= 0.85f ) + { + pos.x = (Rand()-0.5f)*1.0f; + pos.y = (Rand()-0.5f)*1.0f+3.5f; + pos.z = (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = (Rand()*0.3f+0.3f); + dim.y = dim.x; + if ( m_actionType == MT_ERROR ) type = PARTIERROR; + if ( m_actionType == MT_WARNING ) type = PARTIWARNING; + if ( m_actionType == MT_INFO ) type = PARTIINFO; + if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING; + m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Rand()*0.5f, 0.0f, 1.0f, sheet); + + pos.x = 0.50f+(Rand()-0.5f)*0.80f; + pos.y = 0.86f+(Rand()-0.5f)*0.08f; + pos.z = 0.00f; + dim.x = (Rand()*0.04f+0.04f); + dim.y = dim.x/0.75f; + m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); + } + +//? if ( m_bDisplayInfo && m_main->RetGlint() ) + if ( FALSE ) + { + pos.x = (Rand()-0.5f)*1.4f; + pos.y = (Rand()-0.5f)*1.4f+3.5f; + pos.z = (Rand()-0.5f)*1.4f; + pos = Transform(*mat, pos); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = (Rand()*0.5f+0.5f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Rand()*0.5f, 0.0f, 1.0f, sheet); + + for ( i=0 ; i<10 ; i++ ) + { + pos.x = 0.60f+(Rand()-0.5f)*0.76f; + pos.y = 0.47f+(Rand()-0.5f)*0.90f; + pos.z = 0.00f; + r = rand()%4; + if ( r == 0 ) pos.x = 0.21f; // the left edge + else if ( r == 1 ) pos.x = 0.98f; // the right edge + else if ( r == 2 ) pos.y = 0.02f; // on the lower edge + else pos.y = 0.92f; // on the upper edge + dim.x = (Rand()*0.02f+0.02f); + dim.y = dim.x/0.75f; + m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE); + } + } + } + + // Move the sound. + if ( m_soundChannel != -1 ) + { + if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) ) + { + m_soundChannel = -1; + } + } + + return TRUE; +} + + +// Starts an action. + +Error CMotionToto::SetAction(int action, float time) +{ + Sound sound; + + CMotion::SetAction(action, time); + + m_bStartAction = TRUE; + + sound = SOUND_CLICK; + if ( action == MT_ERROR ) sound = SOUND_ERROR; + if ( action == MT_WARNING ) sound = SOUND_WARNING; + if ( action == MT_INFO ) sound = SOUND_INFO; + if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE; + + if ( sound != SOUND_CLICK ) + { + m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0)); + } + + return ERR_OK; +} + +// Specifies the type of the object is attached to toto. + +void CMotionToto::SetLinkType(ObjectType type) +{ + m_type = type; +} + + diff --git a/src/object/motion/motiontoto.h b/src/object/motion/motiontoto.h new file mode 100644 index 0000000..22955bb --- /dev/null +++ b/src/object/motion/motiontoto.h @@ -0,0 +1,81 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motiontoto.h + +#ifndef _MOTIONTOTO_H_ +#define _MOTIONTOTO_H_ + + +#include "struct.h" +#include "object.h" +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; + + +#define MT_ERROR 0 +#define MT_WARNING 1 +#define MT_INFO 2 +#define MT_MESSAGE 3 + + +class CMotionToto : public CMotion +{ +public: + CMotionToto(CInstanceManager* iMan, CObject* object); + ~CMotionToto(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + Error SetAction(int action, float time=0.2f); + void SetLinkType(ObjectType type); + + void StartDisplayInfo(); + void StopDisplayInfo(); + void SetMousePos(FPOINT pos); + +protected: + BOOL EventFrame(const Event &event); + +protected: + float m_time; + float m_lastMotorParticule; + BOOL m_bDisplayInfo; + BOOL m_bQuickPos; + BOOL m_bStartAction; + float m_speedAction; + float m_clownRadius; + float m_clownDelay; + float m_clownTime; + float m_blinkTime; + float m_blinkProgress; + int m_soundChannel; + ObjectType m_type; + FPOINT m_mousePos; +}; + + +#endif //_MOTIONTOTO_H_ diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp new file mode 100644 index 0000000..73dae74 --- /dev/null +++ b/src/object/motion/motionvehicle.cpp @@ -0,0 +1,2091 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionvehicle.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionvehicle.h" + + + +#define ARM_NEUTRAL_ANGLE1 110.0f*PI/180.0f +#define ARM_NEUTRAL_ANGLE2 -130.0f*PI/180.0f +#define ARM_NEUTRAL_ANGLE3 -50.0f*PI/180.0f + + + +// Object's constructor. + +CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + int i; + + CMotion::CMotion(iMan, object); + + for ( i=0 ; i<4 ; i++ ) + { + m_wheelTurn[i] = 0.0f; + } + for ( i=0 ; i<3 ; i++ ) + { + m_flyPaw[i] = 0.0f; + } + m_posTrackLeft = 0.0f; + m_posTrackRight = 0.0f; + m_partiReactor = -1; + m_armTimeAbs = 1000.0f; + m_armMember = 1000.0f; + m_canonTime = 0.0f; + m_lastTimeCanon = 0.0f; + m_wheelLastPos = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_wheelLastAngle = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_posKey = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_bFlyFix = FALSE; + + m_bTraceDown = FALSE; + m_traceColor = 1; // black + m_traceWidth = 0.5f; +} + +// Object's destructor. + +CMotionVehicle::~CMotionVehicle() +{ +} + + +// Removes an object. + +void CMotionVehicle::DeleteObject(BOOL bAll) +{ + if ( m_partiReactor != -1 ) + { + m_particule->DeleteParticule(m_partiReactor); + m_partiReactor = -1; + } +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionVehicle::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + CObject* pPower; + int rank, i, j, parent; + D3DCOLORVALUE color; + char name[50]; + + if ( m_engine->RetRestCreate() < 1+5+18+1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs ) + { + pModFile->ReadModel("objects\\lem1f.mod"); + } + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) + { + pModFile->ReadModel("objects\\lem1t.mod"); + } + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEws ) + { + if ( m_object->RetTrainer() ) + { + pModFile->ReadModel("objects\\lem1wt.mod"); + } + else + { + pModFile->ReadModel("objects\\lem1w.mod"); + } + } + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEis ) + { + pModFile->ReadModel("objects\\lem1i.mod"); + } + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + pModFile->ReadModel("objects\\roller1.mod"); + } + if ( type == OBJECT_MOBILEsa ) + { + pModFile->ReadModel("objects\\subm1.mod"); + } + if ( type == OBJECT_MOBILEtg ) + { + pModFile->ReadModel("objects\\target.mod"); + } + if ( type == OBJECT_MOBILEwt ) + { + pModFile->ReadModel("objects\\trainerw.mod"); + } + if ( type == OBJECT_MOBILEft ) + { + pModFile->ReadModel("objects\\trainerf.mod"); + } + if ( type == OBJECT_MOBILEtt ) + { + pModFile->ReadModel("objects\\trainert.mod"); + } + if ( type == OBJECT_MOBILEit ) + { + pModFile->ReadModel("objects\\traineri.mod"); + } + if ( type == OBJECT_MOBILEdr ) + { + pModFile->ReadModel("objects\\drawer1.mod"); + } + if ( type == OBJECT_APOLLO2 ) + { + pModFile->ReadModel("objects\\apolloj1.mod"); + } + pModFile->CreateEngineObject(rank); + + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have a obligatory collision + // with a sphere of center (0, y, 0) (see GetCrashSphere). + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 7.0f); + } + else if ( type == OBJECT_MOBILEsa ) + { + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 6.0f); + } + else if ( type == OBJECT_MOBILEdr ) + { + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 7.0f); + } + else if ( type == OBJECT_APOLLO2 ) + { + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f); + } + else + { + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 6.0f); + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia ) + { + // Creates the arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\lem2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f)); + m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1); + + // Creates the forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\lem3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(5.0f, 0.0f, 0.0f)); + m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2); + + // Creates the hand. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\lem4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(3.5f, 0.0f, 0.0f)); + m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3); + m_object->SetAngleX(3, PI/2.0f); + + // Creates the close clamp. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 3); + pModFile->ReadModel("objects\\lem5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(1.5f, 0.0f, 0.0f)); + m_object->SetAngleZ(4, -PI*0.10f); + + // Creates the remote clamp. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 3); + pModFile->ReadModel("objects\\lem6.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(1.5f, 0.0f, 0.0f)); + m_object->SetAngleZ(5, PI*0.10f); + } + + if ( type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis ) + { + // Creates the arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\lem2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f)); + m_object->SetAngleZ(1, 110.0f*PI/180.0f); + + // Creates the forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\lem3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(5.0f, 0.0f, 0.0f)); + m_object->SetAngleZ(2, -110.0f*PI/180.0f); + + // Creates the sensor. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\lem4s.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(3.5f, 0.0f, 0.0f)); + m_object->SetAngleZ(3, -65.0f*PI/180.0f); + } + + if ( type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic ) + { + // Creates the cannon. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\canon.mod"); + pModFile->CreateEngineObject(rank); +//? m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f)); + m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f)); + m_object->SetAngleZ(1, 0.0f); + } + + if ( type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii ) + { + // Creates the insect cannon. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\canoni1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 5.3f, 0.0f)); + m_object->SetAngleZ(1, 0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\canoni2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(0.0f, 2.5f, 0.0f)); + m_object->SetAngleZ(2, 0.0f); + } + + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEwt ) + { + // Creates the right-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(-3.0f, 1.0f, -3.0f)); + + // Creates the left-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(-3.0f, 1.0f, 3.0f)); + m_object->SetAngleY(7, PI); + + // Creates the right-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(2.0f, 1.0f, -3.0f)); + + // Creates the left-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(2.0f, 1.0f, 3.0f)); + m_object->SetAngleY(9, PI); + } + + if ( type == OBJECT_MOBILEtg ) + { + // Creates the right-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(-2.0f, 1.0f, -3.0f)); + + // Creates the left-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(-2.0f, 1.0f, 3.0f)); + m_object->SetAngleY(7, PI); + + // Creates the right-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(3.0f, 1.0f, -3.0f)); + + // Creates the left-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 0); + pModFile->ReadModel("objects\\lem2w.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(3.0f, 1.0f, 3.0f)); + m_object->SetAngleY(9, PI); + } + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) // caterpillars? + { + // Creates the right caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\lem2t.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, 2.0f, -3.0f)); + + // Creates the left caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\lem3t.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 2.0f, 3.0f)); + } + + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) // large caterpillars? + { + // Creates the right caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\roller2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, 2.0f, -3.0f)); + + // Creates the left caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\roller3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 2.0f, 3.0f)); + } + + if ( type == OBJECT_MOBILEsa ) // underwater caterpillars? + { + // Creates the right caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\subm4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, 1.0f, -3.0f)); + + // Creates the left caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\subm5.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 1.0f, 3.0f)); + } + + if ( type == OBJECT_MOBILEdr ) // caterpillars? + { + // Creates the right caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\drawer2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(0.0f, 1.0f, -3.0f)); + + // Creates the left caterpillar. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\drawer3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(0.0f, 1.0f, 3.0f)); + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEft ) // flying? + { + // Creates the front foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\lem2f.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(1.7f, 3.0f, 0.0f)); + + // Creates the right-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\lem2f.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(-1.8f, 3.0f, -1.5f)); + m_object->SetAngleY(7, 120.0f*PI/180.0f); + + // Creates the left-back foot. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\lem2f.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(-1.8f, 3.0f, 1.5f)); + m_object->SetAngleY(8, -120.0f*PI/180.0f); + } + + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEii ) // insect legs? + { + float table[] = + { + // x y z + -1.5f, 1.2f, -0.7f, // back leg + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -2.0f, + + 0.0f, 1.2f, -0.9f, // middle leg + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -2.0f, + + 1.5f, 1.2f, -0.7f, // front leg + 0.0f, 0.0f, -1.0f, + 0.0f, 0.0f, -2.0f, + }; + + for ( i=0 ; i<3 ; i++ ) + { + for ( j=0 ; j<3 ; j++ ) + { + sprintf(name, "objects\\ant%d.mod", j+4); // 4..6 + + // Creates the right leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6+i*3+j, rank); + if ( j == 0 ) parent = 0; + else parent = 6+i*3+j-1; + m_object->SetObjectParent(6+i*3+j, parent); + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + pos.x = table[i*9+j*3+0]; + pos.y = table[i*9+j*3+1]; + pos.z = table[i*9+j*3+2]; + m_object->SetPosition(6+i*3+j, pos); + + // Creates the left leg. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(15+i*3+j, rank); + if ( j == 0 ) parent = 0; + else parent = 15+i*3+j-1; + m_object->SetObjectParent(15+i*3+j, parent); + pModFile->ReadModel(name); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + pos.x = table[i*9+j*3+0]; + pos.y = table[i*9+j*3+1]; + pos.z = -table[i*9+j*3+2]; + m_object->SetPosition(15+i*3+j, pos); + } + } + } + + if ( type == OBJECT_MOBILErt ) + { + // Creates the holder. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\roller2t.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetAngleZ(1, 0.0f); + + // Creates the pestle. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\roller3t.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(9.0f, 4.0f, 0.0f)); + m_object->SetAngleZ(2, 0.0f); + } + + if ( type == OBJECT_MOBILErc ) + { + // Creates the holder. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\roller2c.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(3.0f, 4.6f, 0.0f)); + m_object->SetAngleZ(1, PI/8.0f); + + // Creates the cannon. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\roller3p.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(7.0f, 6.5f, 0.0f)); + m_object->SetAngleZ(2, 0.0f); + } + + if ( type == OBJECT_MOBILErr ) + { + // Creates the holder. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\recover1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(2.0f, 5.0f, 0.0f)); + + // Creates the right arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\recover2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(0.1f, 0.0f, -5.0f)); + m_object->SetAngleZ(2, 126.0f*PI/180.0f); + + // Creates the right forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\recover3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(5.0f, 0.0f, -0.5f)); + m_object->SetAngleZ(3, -144.0f*PI/180.0f); + + // Creates the left arm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 1); + pModFile->ReadModel("objects\\recover2.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(4, D3DVECTOR(0.1f, 0.0f, 5.0f)); + m_object->SetAngleZ(4, 126.0f*PI/180.0f); + + // Creates the left forearm. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(5, rank); + m_object->SetObjectParent(5, 4); + pModFile->ReadModel("objects\\recover3.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(5, D3DVECTOR(5.0f, 0.0f, 0.5f)); + m_object->SetAngleZ(5, -144.0f*PI/180.0f); + } + + if ( type == OBJECT_MOBILErs ) + { + // Creates the holder. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\roller2s.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetAngleZ(1, 0.0f); + + // Creates the intermediate piston. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\roller3s.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(7.0f, 4.5f, 0.0f)); + m_object->SetAngleZ(2, 0.0f); + + // Creates the piston with the sphere. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 2); + pModFile->ReadModel("objects\\roller4s.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(0.0f, 1.0f, 0.0f)); + m_object->SetAngleZ(3, 0.0f); + } + + if ( type == OBJECT_MOBILEsa ) + { + // Creates the holder. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\subm2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(4.2f, 3.0f, 0.0f)); + + // Creates the right tong. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 1); + pModFile->ReadModel("objects\\subm3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(0.5f, 0.0f, -1.5f)); + + // Creates the left tong. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(3, rank); + m_object->SetObjectParent(3, 1); + pModFile->ReadModel("objects\\subm3.mod"); + pModFile->Mirror(); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(3, D3DVECTOR(0.5f, 0.0f, 1.5f)); + } + + if ( type == OBJECT_MOBILEdr ) + { + // Creates the carousel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\drawer4.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(-3.0f, 3.0f, 0.0f)); + + // Creates the key. + if ( m_object->RetToy() ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\drawer5.mod"); + pModFile->CreateEngineObject(rank); + m_posKey = D3DVECTOR(3.0f, 5.7f, 0.0f); + m_object->SetPosition(2, m_posKey); + m_object->SetAngleY(2, 90.0f*PI/180.0f); + } + + // Creates pencils. + for ( i=0 ; i<8 ; i++ ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10+i, rank); + m_object->SetObjectParent(10+i, 1); + sprintf(name, "objects\\drawer%d.mod", 10+i); + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10+i, D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetAngleY(10+i, 45.0f*PI/180.0f*i); + } + } + + if ( type == OBJECT_MOBILEwt ) + { + // Creates the key. + if ( m_object->RetToy() ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\drawer5.mod"); + pModFile->CreateEngineObject(rank); + m_posKey = D3DVECTOR(0.2f, 4.1f, 0.0f); + m_object->SetPosition(2, m_posKey); + m_object->SetAngleY(2, 90.0f*PI/180.0f); + } + } + + if ( type == OBJECT_APOLLO2 ) + { + // Creates the accessories. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\apolloj2.mod"); // antenna + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(5.5f, 8.8f, 2.0f)); + m_object->SetAngleY(1, -120.0f*PI/180.0f); + m_object->SetAngleZ(1, 45.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2, rank); + m_object->SetObjectParent(2, 0); + pModFile->ReadModel("objects\\apolloj3.mod"); // camera + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2, D3DVECTOR(5.5f, 2.8f, -2.0f)); + m_object->SetAngleY(2, 30.0f*PI/180.0f); + + // Creates the wheels. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(6, rank); + m_object->SetObjectParent(6, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(6, D3DVECTOR(-5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(7, rank); + m_object->SetObjectParent(7, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(7, D3DVECTOR(-5.75f, 1.65f, 5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(8, rank); + m_object->SetObjectParent(8, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(8, D3DVECTOR(5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(9, rank); + m_object->SetObjectParent(9, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(9, D3DVECTOR(5.75f, 1.65f, 5.00f)); + + // Creates mud guards. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(10, rank); + m_object->SetObjectParent(10, 0); + pModFile->ReadModel("objects\\apolloj6.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(10, D3DVECTOR(-5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(11, rank); + m_object->SetObjectParent(11, 0); + pModFile->ReadModel("objects\\apolloj6.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(11, D3DVECTOR(-5.75f, 1.65f, 5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(12, rank); + m_object->SetObjectParent(12, 0); + pModFile->ReadModel("objects\\apolloj5.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(12, D3DVECTOR(5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(13, rank); + m_object->SetObjectParent(13, 0); + pModFile->ReadModel("objects\\apolloj5.mod"); // wheel + pModFile->CreateEngineObject(rank); + m_object->SetPosition(13, D3DVECTOR(5.75f, 1.65f, 5.00f)); + } + +#if 1 + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + m_object->CreateShadowCircle(6.0f, 1.0f); + } + else if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEsa ) + { + m_object->CreateShadowCircle(5.0f, 1.0f); + } + else if ( type == OBJECT_MOBILEdr ) + { + m_object->CreateShadowCircle(4.5f, 1.0f); + } + else if ( type == OBJECT_APOLLO2 ) + { + m_object->CreateShadowCircle(7.0f, 0.8f); + } + else + { + m_object->CreateShadowCircle(4.0f, 1.0f); + } +#else + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK); + } + else if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) + { + m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK); + } + else if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs ) + { + m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY); + } + else if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEws ) + { + m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL); + } + else if ( type == OBJECT_APOLLO2 ) + { + m_object->CreateShadowCircle(6.0f, 0.8f); + } + else + { + m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM); + } +#endif + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEft ) // flying? + { +//? color.r = 0.5f-1.0f; +//? color.g = 0.2f-1.0f; +//? color.b = 0.0f-1.0f; // orange +//? color.r = 0.8f; +//? color.g = 0.6f; +//? color.b = 0.0f; // yellow-orange + color.r = 0.0f; + color.g = 0.4f; + color.b = 0.8f; // blue + color.a = 0.0f; + m_object->CreateShadowLight(50.0f, color); + } + + CreatePhysics(type); + m_object->SetFloorHeight(0.0f); + + if ( power > 0.0f && + type != OBJECT_MOBILEdr && + type != OBJECT_APOLLO2 ) + { + color.r = 1.0f; + color.g = 1.0f; + color.b = 0.0f; // yellow + color.a = 0.0f; + m_object->CreateEffectLight(20.0f, color); + + // Creates the battery. + pPower = new CObject(m_iMan); + pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + pPower->SetObjectRank(0, rank); + + if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod"); + else pModFile->ReadModel("objects\\atomic.mod"); + pModFile->CreateEngineObject(rank); + + pPower->SetPosition(0, m_object->RetCharacter()->posPower); + pPower->CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + pPower->SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.5f); + + pPower->SetTruck(m_object); + m_object->SetPower(pPower); + + if ( power <= 1.0f ) pPower->SetEnergy(power); + else pPower->SetEnergy(power/100.0f); + } + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); //to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physics of the object. + +void CMotionVehicle::CreatePhysics(ObjectType type) +{ + Character* character; + + character = m_object->RetCharacter(); + + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEwt ) // wheels? + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 3.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.0f; + character->wheelRight = 4.0f; + character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 10.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 8.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 12.0f); + } + + if ( type == OBJECT_MOBILEtg ) + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 4.0f; + character->wheelBack = 3.0f; + character->wheelLeft = 4.0f; + character->wheelRight = 4.0f; + character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 10.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 10.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 15.0f); + } + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) // caterpillars? + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.8f; + character->wheelRight = 4.8f; + character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 8.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 8.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 10.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 6.0f); + } + + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEis ) // legs? + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 5.0f; + character->wheelRight = 5.0f; + character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 8.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 10.0f); +//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 10.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 15.0f); + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEft ) // flying? + { + m_physics->SetType(TYPE_FLYING); + + character->wheelFront = 5.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.5f; + character->wheelRight = 4.5f; + character->posPower = D3DVECTOR(-3.2f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 50.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 20.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f); + m_physics->SetLinMotionY(MO_RECSPEED, 60.0f); + m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionY(MO_RECACCEL, 50.0f); + m_physics->SetLinMotionY(MO_STOACCEL, 50.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 2.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 2.0f); + } + + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) // large caterpillars? + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 5.0f; + character->wheelBack = 5.0f; + character->wheelLeft = 6.0f; + character->wheelRight = 6.0f; + character->posPower = D3DVECTOR(-5.8f, 4.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 5.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 5.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 2.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 4.0f); + } + + if ( type == OBJECT_MOBILEsa ) + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.0f; + character->wheelRight = 4.0f; + character->posPower = D3DVECTOR(-5.0f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 10.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 10.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 5.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 10.0f); + } + + if ( type == OBJECT_MOBILEdr ) + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 4.0f; + character->wheelBack = 4.0f; + character->wheelLeft = 4.0f; + character->wheelRight = 4.0f; + character->posPower = D3DVECTOR(-5.0f, 3.0f, 0.0f); + + m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 10.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 10.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 20.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 5.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 10.0f); + } + + if ( type == OBJECT_APOLLO2 ) // jeep? + { + m_physics->SetType(TYPE_ROLLING); + + character->wheelFront = 6.0f; + character->wheelBack = 6.0f; + character->wheelLeft = 5.0f; + character->wheelRight = 5.0f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 10.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 20.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 30.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 2.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 4.0f); + } +} + + +// Management of an event. + +BOOL CMotionVehicle::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { + } + + return TRUE; +} + +// Management of an event. + +BOOL CMotionVehicle::EventFrame(const Event &event) +{ + D3DMATRIX* mat; + Character* character; + D3DVECTOR pos, angle, floor; + ObjectType type; + float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2; + float back, front, dist, radius, limit[2]; + + if ( m_engine->RetPause() ) return TRUE; + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + type = m_object->RetType(); + + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEtg || + type == OBJECT_APOLLO2 ) // wheels? + { + s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f; + a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f; + + if ( type == OBJECT_APOLLO2 ) s *= 0.5f; + + speedBR = -s+a; + speedBL = s+a; + speedFR = -s+a; + speedFL = s+a; + + m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels + m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL); + m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR); + m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL); + + if ( s > 0.0f ) + { + m_wheelTurn[0] = -a*0.05f; + m_wheelTurn[1] = -a*0.05f+PI; + m_wheelTurn[2] = a*0.05f; + m_wheelTurn[3] = a*0.05f+PI; + } + else if ( s < 0.0f ) + { + m_wheelTurn[0] = a*0.05f; + m_wheelTurn[1] = a*0.05f+PI; + m_wheelTurn[2] = -a*0.05f; + m_wheelTurn[3] = -a*0.05f+PI; + } + else + { + m_wheelTurn[0] = Abs(a)*0.05f; + m_wheelTurn[1] = -Abs(a)*0.05f+PI; + m_wheelTurn[2] = -Abs(a)*0.05f; + m_wheelTurn[3] = Abs(a)*0.05f+PI; + } + m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f); + m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f); + m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f); + m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f); + + if ( type == OBJECT_APOLLO2 ) + { + m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f); + m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+PI); + m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f); + m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+PI); + } + + pos = m_object->RetPosition(0); + angle = m_object->RetAngle(0); + if ( pos.x != m_wheelLastPos.x || + pos.y != m_wheelLastPos.y || + pos.z != m_wheelLastPos.z || + angle.x != m_wheelLastAngle.x || + angle.y != m_wheelLastAngle.y || + angle.z != m_wheelLastAngle.z ) + { + m_wheelLastPos = pos; + m_wheelLastAngle = angle; + + if ( type == OBJECT_MOBILEtg ) + { + back = -2.0f; // back wheels position + front = 3.0f; // front wheels position + dist = 3.0f; // distancing wheels Z + radius = 1.0f; + } + else if ( type == OBJECT_APOLLO2 ) + { + back = -5.75f; // back wheels position + front = 5.75f; // front wheels position + dist = 5.00f; // distancing wheels Z + radius = 1.65f; + } + else + { + back = -3.0f; // back wheels position + front = 2.0f; // front wheels position + dist = 3.0f; // distancing wheels Z + radius = 1.0f; + } + + if ( Length(pos, m_engine->RetEyePt()) < 50.0f ) // suspension? + { + character = m_object->RetCharacter(); + mat = m_object->RetWorldMatrix(0); + + pos.x = -character->wheelBack; // right back wheel + pos.z = -character->wheelRight; + pos.y = 0.0f; + pos = Transform(*mat, pos); + h = m_terrain->RetFloorHeight(pos); + if ( h > 0.5f ) h = 0.5f; + if ( h < -0.5f ) h = -0.5f; + pos.x = back; + pos.y = radius-h; + pos.z = -dist; + m_object->SetPosition(6, pos); + if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos); + + pos.x = -character->wheelBack; // left back wheel + pos.z = character->wheelLeft; + pos.y = 0.0f; + pos = Transform(*mat, pos); + h = m_terrain->RetFloorHeight(pos); + if ( h > 0.5f ) h = 0.5f; + if ( h < -0.5f ) h = -0.5f; + pos.x = back; + pos.y = radius-h; + pos.z = dist; + m_object->SetPosition(7, pos); + if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos); + + pos.x = character->wheelFront; // right front wheel + pos.z = -character->wheelRight; + pos.y = 0.0f; + pos = Transform(*mat, pos); + h = m_terrain->RetFloorHeight(pos); + if ( h > 0.5f ) h = 0.5f; + if ( h < -0.5f ) h = -0.5f; + pos.x = front; + pos.y = radius-h; + pos.z = -dist; + m_object->SetPosition(8, pos); + if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos); + + pos.x = character->wheelFront; // left front wheel + pos.z = character->wheelLeft; + pos.y = 0.0f; + pos = Transform(*mat, pos); + h = m_terrain->RetFloorHeight(pos); + if ( h > 0.5f ) h = 0.5f; + if ( h < -0.5f ) h = -0.5f; + pos.x = front; + pos.y = radius-h; + pos.z = dist; + m_object->SetPosition(9, pos); + if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos); + } + else + { + m_object->SetPosition(6, D3DVECTOR(back, radius, -dist)); + m_object->SetPosition(7, D3DVECTOR(back, radius, dist)); + m_object->SetPosition(8, D3DVECTOR(front, radius, -dist)); + m_object->SetPosition(9, D3DVECTOR(front, radius, dist)); + + if ( type == OBJECT_APOLLO2 ) + { + m_object->SetPosition(10, D3DVECTOR(back, radius, -dist)); + m_object->SetPosition(11, D3DVECTOR(back, radius, dist)); + m_object->SetPosition(12, D3DVECTOR(front, radius, -dist)); + m_object->SetPosition(13, D3DVECTOR(front, radius, dist)); + } + } + } + } + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEdr ) // caterpillars? + { + s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f; + a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f; + + m_posTrackLeft += event.rTime*(s+a); + m_posTrackRight += event.rTime*(s-a); + + UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type); + + pos = m_object->RetPosition(0); + angle = m_object->RetAngle(0); + if ( pos.x != m_wheelLastPos.x || + pos.y != m_wheelLastPos.y || + pos.z != m_wheelLastPos.z || + angle.x != m_wheelLastAngle.x || + angle.y != m_wheelLastAngle.y || + angle.z != m_wheelLastAngle.z ) + { + m_wheelLastPos = pos; + m_wheelLastAngle = angle; + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) + { + limit[0] = 8.0f*PI/180.0f; + limit[1] = -12.0f*PI/180.0f; + } + else if ( type == OBJECT_MOBILEsa ) + { + limit[0] = 15.0f*PI/180.0f; + limit[1] = -15.0f*PI/180.0f; + } + else if ( type == OBJECT_MOBILEdr ) + { + limit[0] = 10.0f*PI/180.0f; + limit[1] = -10.0f*PI/180.0f; + } + else + { + limit[0] = 15.0f*PI/180.0f; + limit[1] = -10.0f*PI/180.0f; + } + + if ( Length(pos, m_engine->RetEyePt()) < 50.0f ) // suspension? + { + character = m_object->RetCharacter(); + mat = m_object->RetWorldMatrix(0); + + pos.x = character->wheelFront; // right front wheel + pos.z = -character->wheelRight; + pos.y = 0.0f; + pos = Transform(*mat, pos); + a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront); + + pos.x = -character->wheelBack; // right back wheel + pos.z = -character->wheelRight; + pos.y = 0.0f; + pos = Transform(*mat, pos); + a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack); + + a = (a2-a1)/2.0f; + if ( a > limit[0] ) a = limit[0]; + if ( a < limit[1] ) a = limit[1]; + m_object->SetAngleZ(6, a); + + pos.x = character->wheelFront; // left front wheel + pos.z = character->wheelLeft; + pos.y = 0.0f; + pos = Transform(*mat, pos); + a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront); + + pos.x = -character->wheelBack; // left back wheel + pos.z = character->wheelLeft; + pos.y = 0.0f; + pos = Transform(*mat, pos); + a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack); + + a = (a2-a1)/2.0f; + if ( a > limit[0] ) a = limit[0]; + if ( a < limit[1] ) a = limit[1]; + m_object->SetAngleZ(7, a); + } + else + { + m_object->SetAngleZ(6, 0.0f); + m_object->SetAngleZ(7, 0.0f); + } + } + } + + if ( type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEdr ) // toy is key? + { + pos = m_posKey; + if ( m_object->RetSelect() && + m_camera->RetType() == CAMERA_ONBOARD ) + { + pos.y += 10.0f; // out of sight! + } + m_object->SetPosition(2, pos); + + s = -Abs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f); + s += -Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f); + m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEft ) // flying? + { + EventFrameFly(event); + } + + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEis ) // legs? + { + EventFrameInsect(event); + } + + if ( type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEii ) // insect cannon? + { + EventFrameCanoni(event); + } + + return TRUE; +} + +// Managing an event for a flying robot. + +BOOL CMotionVehicle::EventFrameFly(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR pos, angle, paw[3]; + float hope[3], actual, final, h, a; + int i; + + pos = m_object->RetPosition(0); + angle = m_object->RetAngle(0); + if ( m_bFlyFix && + pos.x == m_wheelLastPos.x && + pos.y == m_wheelLastPos.y && + pos.z == m_wheelLastPos.z && + angle.x == m_wheelLastAngle.x && + angle.y == m_wheelLastAngle.y && + angle.z == m_wheelLastAngle.z ) return TRUE; + + m_wheelLastPos = pos; + m_wheelLastAngle = angle; + + if ( m_physics->RetLand() ) // on the ground? + { + mat = m_object->RetWorldMatrix(0); + paw[0] = Transform(*mat, D3DVECTOR( 4.2f, 0.0f, 0.0f)); // front + paw[1] = Transform(*mat, D3DVECTOR(-3.0f, 0.0f, -3.7f)); // right back + paw[2] = Transform(*mat, D3DVECTOR(-3.0f, 0.0f, 3.7f)); // left back + + for ( i=0 ; i<3 ; i++ ) + { + h = m_terrain->RetFloorHeight(paw[i]); + a = -atanf(h*0.5f); + if ( a > PI*0.2f ) a = PI*0.2f; + if ( a < -PI*0.2f ) a = -PI*0.2f; + hope[i] = a; + } + } + else // in flight? + { + hope[0] = 0.0f; // front + hope[1] = 0.0f; // right back + hope[2] = 0.0f; // left back + } + + m_bFlyFix = TRUE; + for ( i=0 ; i<3 ; i++ ) + { + actual = m_object->RetAngleZ(6+i); + final = Smooth(actual, hope[i], event.rTime*5.0f); + if ( final != actual ) + { + m_bFlyFix = FALSE; // it is moving + m_object->SetAngleZ(6+i, final); + } + } + + return TRUE; +} + +// Event management for insect legs. + +BOOL CMotionVehicle::EventFrameInsect(const Event &event) +{ + D3DVECTOR dir; + float s, a, prog, time; + int i, st, nd, action; + BOOL bStop, bOnBoard; + + static int table[] = + { + // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air: + 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4 + -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4 + -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4 + // on the ground: + 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4 + -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4 + -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4 + // on the ground back: + 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4 + -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4 + -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4 + // stop: + 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4 + -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4 + -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4 + }; + + bOnBoard = FALSE; + if ( m_object->RetSelect() && + m_camera->RetType() == CAMERA_ONBOARD ) + { + bOnBoard = TRUE; + } + + s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f; + a = Abs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f); + + if ( s == 0.0f && a != 0.0f ) a *= 1.5f; + + m_armTimeAbs += event.rTime; + m_armMember += (s+a)*event.rTime*0.15f; + + bStop = ( a == 0.0f && s == 0.0f ); // stop? + + action = 0; // walking + if ( s == 0.0f && a == 0.0f ) + { + action = 3; // stop + } + + if ( bStop ) + { + prog = Mod(m_armTimeAbs, 2.0f)/10.0f; + a = Mod(m_armMember, 1.0f); + a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly + m_armMember += a; + } + + if ( m_object->RetRuin() ) // burn or explode? + { + action = 3; + } + + for ( i=0 ; i<6 ; i++ ) // the six legs + { + if ( action != 0 ) // special action in progress? + { + st = 3*3*3*action + (i%3)*3; + nd = st; + time = event.rTime*5.0f; + } + else + { + if ( i < 3 ) prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f); + else prog = Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f); + if ( prog < 0.33f ) // t0..t1 ? + { + prog = prog/0.33f; // 0..1 + st = 0; // index start + nd = 1; // index end + } + else if ( prog < 0.67f ) // t1..t2 ? + { + prog = (prog-0.33f)/0.33f; // 0..1 + st = 1; // index start + nd = 2; // index end + } + else // t2..t0 ? + { + prog = (prog-0.67f)/0.33f; // 0..1 + st = 2; // index start + nd = 0; // index end + } + st = 3*3*3*action + st*3*3*3 + (i%3)*3; + nd = 3*3*3*action + nd*3*3*3 + (i%3)*3; + + // Less and less soft ... + time = event.rTime*20.0f; + } + + if ( i < 3 ) // right leg (1..3) ? + { + m_object->SetAngleX(6+3*i+0, Smooth(m_object->RetAngleX(6+3*i+0), Prop(table[st+ 0], table[nd+ 0], prog), time)); + m_object->SetAngleY(6+3*i+0, Smooth(m_object->RetAngleY(6+3*i+0), Prop(table[st+ 1], table[nd+ 1], prog), time)); + m_object->SetAngleZ(6+3*i+0, Smooth(m_object->RetAngleZ(6+3*i+0), Prop(table[st+ 2], table[nd+ 2], prog), time)); + m_object->SetAngleX(6+3*i+1, Smooth(m_object->RetAngleX(6+3*i+1), Prop(table[st+ 9], table[nd+ 9], prog), time)); + m_object->SetAngleY(6+3*i+1, Smooth(m_object->RetAngleY(6+3*i+1), Prop(table[st+10], table[nd+10], prog), time)); + m_object->SetAngleZ(6+3*i+1, Smooth(m_object->RetAngleZ(6+3*i+1), Prop(table[st+11], table[nd+11], prog), time)); + m_object->SetAngleX(6+3*i+2, Smooth(m_object->RetAngleX(6+3*i+2), Prop(table[st+18], table[nd+18], prog), time)); + m_object->SetAngleY(6+3*i+2, Smooth(m_object->RetAngleY(6+3*i+2), Prop(table[st+19], table[nd+19], prog), time)); + m_object->SetAngleZ(6+3*i+2, Smooth(m_object->RetAngleZ(6+3*i+2), Prop(table[st+20], table[nd+20], prog), time)); + } + else // left leg (4..6) ? + { + m_object->SetAngleX(6+3*i+0, Smooth(m_object->RetAngleX(6+3*i+0), Prop(-table[st+ 0], -table[nd+ 0], prog), time)); + m_object->SetAngleY(6+3*i+0, Smooth(m_object->RetAngleY(6+3*i+0), Prop(-table[st+ 1], -table[nd+ 1], prog), time)); + m_object->SetAngleZ(6+3*i+0, Smooth(m_object->RetAngleZ(6+3*i+0), Prop( table[st+ 2], table[nd+ 2], prog), time)); + m_object->SetAngleX(6+3*i+1, Smooth(m_object->RetAngleX(6+3*i+1), Prop(-table[st+ 9], -table[nd+ 9], prog), time)); + m_object->SetAngleY(6+3*i+1, Smooth(m_object->RetAngleY(6+3*i+1), Prop(-table[st+10], -table[nd+10], prog), time)); + m_object->SetAngleZ(6+3*i+1, Smooth(m_object->RetAngleZ(6+3*i+1), Prop( table[st+11], table[nd+11], prog), time)); + m_object->SetAngleX(6+3*i+2, Smooth(m_object->RetAngleX(6+3*i+2), Prop(-table[st+18], -table[nd+18], prog), time)); + m_object->SetAngleY(6+3*i+2, Smooth(m_object->RetAngleY(6+3*i+2), Prop(-table[st+19], -table[nd+19], prog), time)); + m_object->SetAngleZ(6+3*i+2, Smooth(m_object->RetAngleZ(6+3*i+2), Prop( table[st+20], table[nd+20], prog), time)); + } + } + + if ( bStop ) + { + } + else + { + a = Mod(m_armMember, 1.0f); + if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1 + else a = 3.0f-4.0f*a; // 1..-1 + dir.x = sinf(a)*0.05f; + + s = Mod(m_armMember/2.0f, 1.0f); + if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1 + else s = 3.0f-4.0f*s; // 1..-1 + dir.z = sinf(s)*0.1f; + + dir.y = 0.0f; + + if ( bOnBoard ) dir *= 0.6f; + SetInclinaison(dir); + } + + return TRUE; +} + +// Event management for a insect cannon. + +BOOL CMotionVehicle::EventFrameCanoni(const Event &event) +{ + CObject* power; + D3DVECTOR pos, speed; + FPOINT dim; + float zoom, angle, energy, factor; + BOOL bOnBoard = FALSE; + + m_canonTime += event.rTime; + + if ( m_object->RetSelect() && + m_camera->RetType() == CAMERA_ONBOARD ) + { + bOnBoard = TRUE; + } + + power = m_object->RetPower(); + if ( power == 0 ) + { + energy = 0.0f; + } + else + { + energy = power->RetEnergy(); + } + if ( energy == 0.0f ) return TRUE; + + factor = 0.5f+energy*0.5f; + if ( bOnBoard ) factor *= 0.8f; + + zoom = 1.3f+ + sinf(m_canonTime*PI*0.31f)*0.10f+ + sinf(m_canonTime*PI*0.52f)*0.08f+ + sinf(m_canonTime*PI*1.53f)*0.05f; + zoom *= factor; + m_object->SetZoomY(2, zoom); + + zoom = 1.0f+ + sinf(m_canonTime*PI*0.27f)*0.07f+ + sinf(m_canonTime*PI*0.62f)*0.06f+ + sinf(m_canonTime*PI*1.73f)*0.03f; + zoom *= factor; + m_object->SetZoomZ(2, zoom); + + angle = sinf(m_canonTime*1.0f)*0.10f+ + sinf(m_canonTime*1.3f)*0.15f+ + sinf(m_canonTime*2.7f)*0.05f; + m_object->SetAngleX(2, angle); + +#if 0 + m_lastTimeCanon -= event.rTime; + if ( m_lastTimeCanon <= 0.0f ) + { + m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Rand()*0.5f); + + pos = m_object->RetPosition(0); + pos.y += 8.0f; + speed.y = 7.0f+Rand()*3.0f; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = 2.0f+Rand()*2.0f; + if ( Rand() < 0.5f ) speed.z = -speed.z; + mat = m_object->RetRotateMatrix(0); + speed = Transform(*mat, speed); + dim.x = Rand()*0.1f+0.1f; + if ( bOnBoard ) dim.x *= 0.4f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f); + } +#endif + + return TRUE; +} + + +// Updates the mapping of the texture of the caterpillars. + +void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type) +{ + D3DMATERIAL7 mat; + float limit[4]; + int rRank, lRank, i; + + ZeroMemory( &mat, sizeof(D3DMATERIAL7) ); + mat.diffuse.r = 1.0f; + mat.diffuse.g = 1.0f; + mat.diffuse.b = 1.0f; // white + mat.ambient.r = 0.5f; + mat.ambient.g = 0.5f; + mat.ambient.b = 0.5f; + + rRank = m_object->RetObjectRank(6); + lRank = m_object->RetObjectRank(7); + + + if ( type == OBJECT_MOBILEdr ) + { + limit[0] = 0.0f; + limit[1] = 1000000.0f; + limit[2] = limit[1]; + limit[3] = m_engine->RetLimitLOD(1); + + m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "", + limit[0], limit[1], D3DMAPPINGX, + right, 1.0f, 8.0f, 192.0f, 256.0f); + + m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "", + limit[0], limit[1], D3DMAPPINGX, + left, 1.0f, 8.0f, 192.0f, 256.0f); + } + else + { + limit[0] = 0.0f; + limit[1] = m_engine->RetLimitLOD(0); + limit[2] = limit[1]; + limit[3] = m_engine->RetLimitLOD(1); + + for ( i=0 ; i<2 ; i++ ) + { + m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "", + limit[i*2+0], limit[i*2+1], D3DMAPPINGX, + right, 1.0f, 8.0f, 192.0f, 256.0f); + + m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "", + limit[i*2+0], limit[i*2+1], D3DMAPPINGX, + left, 1.0f, 8.0f, 192.0f, 256.0f); + } + } + +} + + + +// State management of the pencil drawing robot. + +BOOL CMotionVehicle::RetTraceDown() +{ + return m_bTraceDown; +} + +void CMotionVehicle::SetTraceDown(BOOL bDown) +{ + m_bTraceDown = bDown; +} + +int CMotionVehicle::RetTraceColor() +{ + return m_traceColor; +} + +void CMotionVehicle::SetTraceColor(int color) +{ + m_traceColor = color; +} + +float CMotionVehicle::RetTraceWidth() +{ + return m_traceWidth; +} + +void CMotionVehicle::SetTraceWidth(float width) +{ + m_traceWidth = width; +} + + diff --git a/src/object/motion/motionvehicle.h b/src/object/motion/motionvehicle.h new file mode 100644 index 0000000..1b351c4 --- /dev/null +++ b/src/object/motion/motionvehicle.h @@ -0,0 +1,82 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionvehicle.h + +#ifndef _MOTIONVEHICLE_H_ +#define _MOTIONVEHICLE_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +class CMotionVehicle : public CMotion +{ +public: + CMotionVehicle(CInstanceManager* iMan, CObject* object); + ~CMotionVehicle(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + + BOOL RetTraceDown(); + void SetTraceDown(BOOL bDown); + int RetTraceColor(); + void SetTraceColor(int color); + float RetTraceWidth(); + void SetTraceWidth(float width); + +protected: + void CreatePhysics(ObjectType type); + BOOL EventFrame(const Event &event); + BOOL EventFrameFly(const Event &event); + BOOL EventFrameInsect(const Event &event); + BOOL EventFrameCanoni(const Event &event); + void UpdateTrackMapping(float left, float right, ObjectType type); + +protected: + float m_wheelTurn[4]; + float m_flyPaw[3]; + float m_posTrackLeft; + float m_posTrackRight; + int m_partiReactor; + float m_armTimeAbs; + float m_armMember; + float m_canonTime; + float m_lastTimeCanon; + D3DVECTOR m_wheelLastPos; + D3DVECTOR m_wheelLastAngle; + D3DVECTOR m_posKey; + BOOL m_bFlyFix; + BOOL m_bTraceDown; + int m_traceColor; + float m_traceWidth; +}; + + +#endif //_MOTIONVEHICLE_H_ diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp new file mode 100644 index 0000000..eb32b44 --- /dev/null +++ b/src/object/motion/motionworm.cpp @@ -0,0 +1,380 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionworm.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "modfile.h" +#include "sound.h" +#include "motion.h" +#include "motionworm.h" + + + +#define START_TIME 1000.0f // beginning of the relative time +#define TIME_UPDOWN 2.0f // time for up / down +#define DOWN_ALTITUDE 3.0f // underground distance +#define WORM_PART 7 // number of parts of a worm + + + +// Object's constructor. + +CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object) + : CMotion(iMan, object) +{ + CMotion::CMotion(iMan, object); + + m_timeUp = 18.0f; + m_timeDown = 18.0f; + m_armMember = START_TIME; + m_armTimeAbs = START_TIME; + m_armTimeMarch = START_TIME; + m_armTimeAction = START_TIME; + m_armTimeIndex = 0; + m_armPartIndex = 0; + m_armMemberIndex = 0; + m_armLinSpeed = 0.0f; + m_armCirSpeed = 0.0f; + m_armLastAction = -1; + m_specAction = -1; + m_lastParticule = 0.0f; + m_bArmStop = FALSE; +} + +// Object's destructor. + +CMotionWorm::~CMotionWorm() +{ +} + + +// Removes an object. + +void CMotionWorm::DeleteObject(BOOL bAll) +{ +} + + +// Creates a vehicle traveling any lands on the ground. + +BOOL CMotionWorm::Create(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + int rank, i; + float px; + + if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + m_object->SetType(type); + + // Creates the main base. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object + m_object->SetObjectRank(0, rank); + pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose! + pModFile->CreateEngineObject(rank); + m_object->SetPosition(0, pos); + m_object->SetAngleY(0, angle); + + // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere). + m_object->CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f); + m_object->SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 5.0f); + + px = 1.0f+WORM_PART/2; + + // Creates the head. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + pModFile->ReadModel("objects\\worm1.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(1, D3DVECTOR(px, 0.0f, 0.0f)); + px -= 1.0f; + + // Creates the body. + for ( i=0 ; iCreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2+i, rank); + m_object->SetObjectParent(2+i, 0); + pModFile->ReadModel("objects\\worm2.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2+i, D3DVECTOR(px, 0.0f, 0.0f)); + px -= 1.0f; + } + + // Creates the tail. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + m_object->SetObjectRank(2+WORM_PART, rank); + m_object->SetObjectParent(2+WORM_PART, 0); + pModFile->ReadModel("objects\\worm3.mod"); + pModFile->CreateEngineObject(rank); + m_object->SetPosition(2+WORM_PART, D3DVECTOR(px, 0.0f, 0.0f)); + + m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM); + + CreatePhysics(); + m_object->SetFloorHeight(0.0f); + + pos = m_object->RetPosition(0); + m_object->SetPosition(0, pos); // to display the shadows immediately + + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates the physics of the object. + +void CMotionWorm::CreatePhysics() +{ + Character* character; + + m_physics->SetType(TYPE_ROLLING); + + character = m_object->RetCharacter(); + character->wheelFront = 10.0f; + character->wheelBack = 10.0f; + character->wheelLeft = 2.0f; + character->wheelRight = 2.0f; + character->height = -0.2f; + + m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f); + m_physics->SetLinMotionX(MO_RECSPEED, 3.0f); + m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f); + m_physics->SetLinMotionX(MO_RECACCEL, 10.0f); + m_physics->SetLinMotionX(MO_STOACCEL, 40.0f); + m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f); + m_physics->SetLinMotionX(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f); + m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f); + + m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*PI); + m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*PI); + m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f); + m_physics->SetCirMotionY(MO_RECACCEL, 10.0f); + m_physics->SetCirMotionY(MO_STOACCEL, 20.0f); +} + + + +// Specifies a special parameter. + +BOOL CMotionWorm::SetParam(int rank, float value) +{ + if ( rank == 0 ) + { + m_timeDown = value; + return TRUE; + } + + if ( rank == 1 ) + { + m_timeUp = value; + return TRUE; + } + + return FALSE; +} + +float CMotionWorm::RetParam(int rank) +{ + if ( rank == 0 ) return m_timeDown; + if ( rank == 1 ) return m_timeUp; + return 0.0f; +} + + + +// Management of an event. + +BOOL CMotionWorm::EventProcess(const Event &event) +{ + CMotion::EventProcess(event); + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + if ( event.event == EVENT_KEYDOWN ) + { + } + + return TRUE; +} + +// Management of an event. + +BOOL CMotionWorm::EventFrame(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR pos, p, angle, speed; + FPOINT center, pp, dim; + float height[WORM_PART+2]; + float floor, a, s, px, curve, phase, h, zoom, radius; + int i, under; + + if ( m_engine->RetPause() ) return TRUE; + + s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED); + a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED); + + if ( s == 0.0f && a != 0.0f ) s = a; + + m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f; + m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f; + + m_armTimeAbs += event.rTime; + m_armTimeMarch += event.rTime*m_armLinSpeed; + + under = 0; // no piece under the ground + for ( i=0 ; iRetBurn() ) // is burning? + { + h = 0.0f; // remains on earth + } + h += 0.3f; + height[i] = h; + } + m_object->SetVisible(under!=WORM_PART+2); + + if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return TRUE; + + pos = m_object->RetPosition(0); + floor = m_terrain->RetFloorLevel(pos, TRUE); + + mat = m_object->RetWorldMatrix(0); + + px = 1.0f+WORM_PART/2; + for ( i=0 ; iSetObjectShadowRadius(m_object->RetObjectRank(0), radius); + + pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f; + pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed; + pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f; + pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f; + + curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f; + center.x = 0.0f; + center.y = 0.0f; + pp.x = pos.x; + pp.y = pos.z; + pp = RotatePoint(center, curve, pp); + pos.x = pp.x; + pos.z = pp.y; + + p = Transform(*mat, pos); + pos.y += m_terrain->RetFloorLevel(p, TRUE)-floor; + m_object->SetPosition(i+1, pos); + + zoom = Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f); + if ( zoom > 1.0f ) zoom = 2.0f-zoom; + zoom *= 1.6f; + if ( zoom < 1.0f ) zoom = 1.0f; + m_object->SetZoomY(i+1, 0.2f+zoom*0.8f); + m_object->SetZoomZ(i+1, zoom); + + if ( height[i] >= -1.0f && height[i] < -0.2f && + m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch ) + { + m_lastParticule = m_armTimeMarch; + + pos = p; + pos.y += -height[i]; + pos.x += (Rand()-0.5f)*4.0f; + pos.z += (Rand()-0.5f)*4.0f; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = Rand()*2.0f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + } + + px -= 1.0f; + } + + for ( i=0 ; iRetPosition(i+2); + pos -= m_object->RetPosition(i+1); + + angle.z = -RotateAngle(Length(pos.x, pos.z), pos.y); + angle.y = PI-RotateAngle(pos.x, pos.z); + angle.x = 0.0f; + m_object->SetAngle(i+1, angle); + + if ( i == WORM_PART ) + { + m_object->SetAngle(i+2, angle); + } + } + + return TRUE; +} + + diff --git a/src/object/motion/motionworm.h b/src/object/motion/motionworm.h new file mode 100644 index 0000000..cabb2ba --- /dev/null +++ b/src/object/motion/motionworm.h @@ -0,0 +1,75 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// motionworm.h + +#ifndef _MOTIONWORM_H_ +#define _MOTIONWORM_H_ + + +#include "motion.h" + + +class CInstanceManager; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CCamera; +class CBrain; +class CPhysics; +class CObject; + + +class CMotionWorm : public CMotion +{ +public: + CMotionWorm(CInstanceManager* iMan, CObject* object); + ~CMotionWorm(); + + void DeleteObject(BOOL bAll=FALSE); + BOOL Create(D3DVECTOR pos, float angle, ObjectType type, float power); + BOOL EventProcess(const Event &event); + + BOOL SetParam(int rank, float value); + float RetParam(int rank); + +protected: + void CreatePhysics(); + BOOL EventFrame(const Event &event); + +protected: + float m_timeUp; + float m_timeDown; + float m_armMember; + float m_armTimeAbs; + float m_armTimeMarch; + float m_armTimeAction; + short m_armAngles[3*3*3*3*10]; + int m_armTimeIndex; + int m_armPartIndex; + int m_armMemberIndex; + int m_armLastAction; + float m_armLinSpeed; + float m_armCirSpeed; + int m_specAction; + float m_specTime; + BOOL m_bArmStop; + float m_lastParticule; +}; + + +#endif //_MOTIONWORM_H_ diff --git a/src/object/object.cpp b/src/object/object.cpp new file mode 100644 index 0000000..0757e46 --- /dev/null +++ b/src/object/object.cpp @@ -0,0 +1,7607 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// object.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "CBot/CBotDll.h" +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "d3dutil.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "restext.h" +#include "math3d.h" +#include "mainmovie.h" +#include "robotmain.h" +#include "light.h" +#include "terrain.h" +#include "water.h" +#include "blitz.h" +#include "camera.h" +#include "particule.h" +#include "physics.h" +#include "brain.h" +#include "motion.h" +#include "motionhuman.h" +#include "motiontoto.h" +#include "motionvehicle.h" +#include "motionmother.h" +#include "motionant.h" +#include "motionspider.h" +#include "motionbee.h" +#include "motionworm.h" +#include "modfile.h" +#include "auto.h" +#include "autobase.h" +#include "autoportico.h" +#include "autoderrick.h" +#include "autofactory.h" +#include "autorepair.h" +#include "autodestroyer.h" +#include "autostation.h" +#include "autoenergy.h" +#include "autoconvert.h" +#include "autotower.h" +#include "autoresearch.h" +#include "autolabo.h" +#include "autonuclear.h" +#include "autoradar.h" +#include "autoegg.h" +#include "autonest.h" +#include "autoroot.h" +#include "autoflag.h" +#include "autoinfo.h" +#include "autojostle.h" +#include "autopara.h" +#include "autosafe.h" +#include "autohuston.h" +#include "automush.h" +#include "autokid.h" +#include "task.h" +#include "pyro.h" +#include "displaytext.h" +#include "cmdtoken.h" +#include "cbottoken.h" +#include "sound.h" +#include "object.h" + + + +#define ADJUST_ONBOARD FALSE // TRUE -> adjusts the camera ONBOARD +#define ADJUST_ARM FALSE // TRUE -> adjusts the manipulator arm +#define VIRUS_DELAY 60.0f // duration of virus infection +#define LOSS_SHIELD 0.24f // loss of the shield by shot +#define LOSS_SHIELD_H 0.10f // loss of the shield for humans +#define LOSS_SHIELD_M 0.02f // loss of the shield for the laying + +#if ADJUST_ONBOARD +static float debug_x = 0.0f; +static float debug_y = 0.0f; +static float debug_z = 0.0f; +#endif + +#if ADJUST_ARM +static float debug_arm1 = 0.0f; +static float debug_arm2 = 0.0f; +static float debug_arm3 = 0.0f; +#endif + + + + +// Updates the class Object. + +void uObject(CBotVar* botThis, void* user) +{ + CObject* object = (CObject*)user; + CObject* power; + CObject* fret; + CPhysics* physics; + CBotVar *pVar, *pSub; + ObjectType type; + D3DVECTOR pos; + float value; + int iValue; + + if ( object == 0 ) return; + + physics = object->RetPhysics(); + + // Updates the object's type. + pVar = botThis->GivItemList(); // "category" + type = object->RetType(); + pVar->SetValInt(type, object->RetName()); + + // Updates the position of the object. + pVar = pVar->GivNext(); // "position" + if ( object->RetTruck() == 0 ) + { + pos = object->RetPosition(0); + pos.y -= object->RetWaterLevel(); // relative to sea level! + pSub = pVar->GivItemList(); // "x" + pSub->SetValFloat(pos.x/g_unit); + pSub = pSub->GivNext(); // "y" + pSub->SetValFloat(pos.z/g_unit); + pSub = pSub->GivNext(); // "z" + pSub->SetValFloat(pos.y/g_unit); + } + else // object transported? + { + pSub = pVar->GivItemList(); // "x" + pSub->SetInit(IS_NAN); + pSub = pSub->GivNext(); // "y" + pSub->SetInit(IS_NAN); + pSub = pSub->GivNext(); // "z" + pSub->SetInit(IS_NAN); + } + + // Updates the angle. + pos = object->RetAngle(0); + pos += object->RetInclinaison(); + pVar = pVar->GivNext(); // "orientation" + pVar->SetValFloat(360.0f-Mod(pos.y*180.0f/PI, 360.0f)); + pVar = pVar->GivNext(); // "pitch" + pVar->SetValFloat(pos.z*180.0f/PI); + pVar = pVar->GivNext(); // "roll" + pVar->SetValFloat(pos.x*180.0f/PI); + + // Updates the energy level of the object. + pVar = pVar->GivNext(); // "energyLevel" + value = object->RetEnergy(); + pVar->SetValFloat(value); + + // Updates the shield level of the object. + pVar = pVar->GivNext(); // "shieldLevel" + value = object->RetShield(); + pVar->SetValFloat(value); + + // Updates the temperature of the reactor. + pVar = pVar->GivNext(); // "temperature" + if ( physics == 0 ) value = 0.0f; + else value = 1.0f-physics->RetReactorRange(); + pVar->SetValFloat(value); + + // Updates the height above the ground. + pVar = pVar->GivNext(); // "altitude" + if ( physics == 0 ) value = 0.0f; + else value = physics->RetFloorHeight(); + pVar->SetValFloat(value/g_unit); + + // Updates the lifetime of the object. + pVar = pVar->GivNext(); // "lifeTime" + value = object->RetAbsTime(); + pVar->SetValFloat(value); + + // Updates the material of the object. + pVar = pVar->GivNext(); // "material" + iValue = object->RetMaterial(); + pVar->SetValInt(iValue); + + // Updates the type of battery. + pVar = pVar->GivNext(); // "energyCell" + power = object->RetPower(); + if ( power == 0 ) pVar->SetPointer(0); + else pVar->SetPointer(power->RetBotVar()); + + // Updates the transported object's type. + pVar = pVar->GivNext(); // "load" + fret = object->RetFret(); + if ( fret == 0 ) pVar->SetPointer(0); + else pVar->SetPointer(fret->RetBotVar()); +} + + + + +// Object's constructor. + +CObject::CObject(CInstanceManager* iMan) +{ + int i; + + m_iMan = iMan; + m_iMan->AddInstance(CLASS_OBJECT, this, 500); + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + m_physics = 0; + m_brain = 0; + m_motion = 0; + m_auto = 0; + m_runScript = 0; + + m_type = OBJECT_FIX; + m_id = ++g_id; + m_option = 0; + m_name[0] = 0; + m_partiReactor = -1; + m_shadowLight = -1; + m_effectLight = -1; + m_linVibration = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_cirVibration = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_inclinaison = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_lastParticule = 0.0f; + + m_power = 0; + m_fret = 0; + m_truck = 0; + m_truckLink = 0; + m_energy = 1.0f; + m_capacity = 1.0f; + m_shield = 1.0f; + m_range = 0.0f; + m_transparency = 0.0f; + m_lastEnergy = 999.9f; + m_bHilite = FALSE; + m_bSelect = FALSE; + m_bSelectable = TRUE; + m_bCheckToken = TRUE; + m_bVisible = TRUE; + m_bEnable = TRUE; + m_bGadget = FALSE; + m_bProxyActivate = FALSE; + m_bTrainer = FALSE; + m_bToy = FALSE; + m_bManual = FALSE; + m_bFixed = FALSE; + m_bClip = TRUE; + m_bShowLimit = FALSE; + m_showLimitRadius = 0.0f; + m_aTime = 0.0f; + m_shotTime = 0.0f; + m_bVirusMode = FALSE; + m_virusTime = 0.0f; + m_lastVirusParticule = 0.0f; + m_totalDesectList = 0; + m_bLock = FALSE; + m_bExplo = FALSE; + m_bCargo = FALSE; + m_bBurn = FALSE; + m_bDead = FALSE; + m_bFlat = FALSE; + m_gunGoalV = 0.0f; + m_gunGoalH = 0.0f; + m_shieldRadius = 0.0f; + m_defRank = -1; + m_magnifyDamage = 1.0f; + m_proxyDistance = 60.0f; + m_param = 0.0f; + + ZeroMemory(&m_character, sizeof(Character)); + m_character.wheelFront = 1.0f; + m_character.wheelBack = 1.0f; + m_character.wheelLeft = 1.0f; + m_character.wheelRight = 1.0f; + + m_resetCap = RESET_NONE; + m_bResetBusy = FALSE; + m_resetPosition = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_resetAngle = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_resetRun = -1; + + m_cameraType = CAMERA_BACK; + m_cameraDist = 50.0f; + m_bCameraLock = FALSE; + + m_infoTotal = 0; + m_infoReturn = NAN; + m_bInfoUpdate = FALSE; + + for ( i=0 ; iAddUpdateFunc(uObject); + } + + m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object")); + m_botVar->SetUserPtr(this); + m_botVar->SetIdent(m_id); +} + +// Object's destructor. + +CObject::~CObject() +{ + if ( m_botVar != 0 ) + { + m_botVar->SetUserPtr(OBJECTDELETED); + delete m_botVar; + } + + delete m_physics; + delete m_brain; + delete m_motion; + delete m_auto; + + m_iMan->DeleteInstance(CLASS_OBJECT, this); +} + + +// Removes an object. +// If bAll = TRUE, it does not help, +// because all objects in the scene are quickly destroyed! + +void CObject::DeleteObject(BOOL bAll) +{ + CObject* pObj; + CPyro* pPyro; + int i; + + if ( m_botVar != 0 ) + { + m_botVar->SetUserPtr(OBJECTDELETED); + } + + if ( m_camera->RetObject() == this ) + { + m_camera->SetObject(0); + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + pObj->DeleteDeselList(this); + } + + if ( !bAll ) + { +#if 0 + type = m_camera->RetType(); + if ( (type == CAMERA_BACK || + type == CAMERA_FIX || + type == CAMERA_EXPLO || + type == CAMERA_ONBOARD) && + m_camera->RetObject() == this ) + { + pObj = m_main->SearchNearest(RetPosition(0), this); + if ( pObj == 0 ) + { + m_camera->SetObject(0); + m_camera->SetType(CAMERA_FREE); + } + else + { + m_camera->SetObject(pObj); + m_camera->SetType(CAMERA_BACK); + } + } +#endif + for ( i=0 ; i<1000000 ; i++ ) + { + pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i); + if ( pPyro == 0 ) break; + + pPyro->CutObjectLink(this); // the object no longer exists + } + + if ( m_bSelect ) + { + SetSelect(FALSE); + } + + if ( m_type == OBJECT_BASE || + m_type == OBJECT_FACTORY || + m_type == OBJECT_REPAIR || + m_type == OBJECT_DESTROYER|| + m_type == OBJECT_DERRICK || + m_type == OBJECT_STATION || + m_type == OBJECT_CONVERT || + m_type == OBJECT_TOWER || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_RADAR || + m_type == OBJECT_INFO || + m_type == OBJECT_ENERGY || + m_type == OBJECT_LABO || + m_type == OBJECT_NUCLEAR || + m_type == OBJECT_PARA || + m_type == OBJECT_SAFE || + m_type == OBJECT_HUSTON || + m_type == OBJECT_START || + m_type == OBJECT_END ) // building? + { + m_terrain->DeleteBuildingLevel(RetPosition(0)); // flattens the field + } + } + + m_type = OBJECT_NULL; // invalid object until complete destruction + + if ( m_partiReactor != -1 ) + { + m_particule->DeleteParticule(m_partiReactor); + m_partiReactor = -1; + } + + if ( m_shadowLight != -1 ) + { + m_light->DeleteLight(m_shadowLight); + m_shadowLight = -1; + } + + if ( m_effectLight != -1 ) + { + m_light->DeleteLight(m_effectLight); + m_effectLight = -1; + } + + if ( m_physics != 0 ) + { + m_physics->DeleteObject(bAll); + } + + if ( m_brain != 0 ) + { + m_brain->DeleteObject(bAll); + } + + if ( m_motion != 0 ) + { + m_motion->DeleteObject(bAll); + } + + if ( m_auto != 0 ) + { + m_auto->DeleteObject(bAll); + } + + for ( i=0 ; iDeleteObject(m_objectPart[i].object); + + if ( m_objectPart[i].masterParti != -1 ) + { + m_particule->DeleteParticule(m_objectPart[i].masterParti); + m_objectPart[i].masterParti = -1; + } + } + } + + if ( m_bShowLimit ) + { + m_main->FlushShowLimit(0); + m_bShowLimit = FALSE; + } + + if ( !bAll ) m_main->CreateShortcuts(); +} + +// Simplifies a object (he was the brain, among others). + +void CObject::Simplify() +{ + if ( m_brain != 0 ) + { + m_brain->StopProgram(); + } + m_main->SaveOneScript(this); + + if ( m_physics != 0 ) + { + m_physics->DeleteObject(); + delete m_physics; + m_physics = 0; + } + + if ( m_brain != 0 ) + { + m_brain->DeleteObject(); + delete m_brain; + m_brain = 0; + } + + if ( m_motion != 0 ) + { + m_motion->DeleteObject(); + delete m_motion; + m_motion = 0; + } + + if ( m_auto != 0 ) + { + m_auto->DeleteObject(); + delete m_auto; + m_auto = 0; + } + + m_main->CreateShortcuts(); +} + + +// Detonates an object, when struck by a shot. +// If FALSE is returned, the object is still screwed. +// If TRUE is returned, the object is destroyed. + +BOOL CObject::ExploObject(ExploType type, float force, float decay) +{ + PyroType pyroType; + CPyro* pyro; + float loss, shield; + + if ( type == EXPLO_BURN ) + { + if ( m_type == OBJECT_MOBILEtg || + m_type == OBJECT_TEEN28 || // cylinder? + m_type == OBJECT_METAL || + m_type == OBJECT_POWER || + m_type == OBJECT_ATOMIC || + m_type == OBJECT_TNT || + m_type == OBJECT_SCRAP1 || + m_type == OBJECT_SCRAP2 || + m_type == OBJECT_SCRAP3 || + m_type == OBJECT_SCRAP4 || + m_type == OBJECT_SCRAP5 || + m_type == OBJECT_BULLET || + m_type == OBJECT_EGG ) // object that isn't burning? + { + type = EXPLO_BOUM; + force = 1.0f; + decay = 1.0f; + } + } + + if ( EXPLO_BOUM ) + { + if ( m_shotTime < 0.5f ) return FALSE; + m_shotTime = 0.0f; + } + + if ( m_type == OBJECT_HUMAN && m_bDead ) return FALSE; + + // Calculate the power lost by the explosion. + if ( force == 0.0f ) + { + if ( m_type == OBJECT_HUMAN ) + { + loss = LOSS_SHIELD_H; + } + else if ( m_type == OBJECT_MOTHER ) + { + loss = LOSS_SHIELD_M; + } + else + { + loss = LOSS_SHIELD; + } + } + else + { + loss = force; + } + loss *= m_magnifyDamage; + loss *= decay; + + // Decreases the power of the shield. + shield = RetShield(); + shield -= loss; + if ( shield < 0.0f ) shield = 0.0f; + SetShield(shield); + + if ( shield > 0.0f ) // not dead yet? + { + if ( type == EXPLO_WATER ) + { + if ( m_type == OBJECT_HUMAN ) + { + pyroType = PT_SHOTH; + } + else + { + pyroType = PT_SHOTW; + } + } + else + { + if ( m_type == OBJECT_HUMAN ) + { + pyroType = PT_SHOTH; + } + else if ( m_type == OBJECT_MOTHER ) + { + pyroType = PT_SHOTM; + } + else + { + pyroType = PT_SHOTT; + } + } + } + else // completely dead? + { + if ( type == EXPLO_BURN ) // burning? + { + if ( m_type == OBJECT_MOTHER || + m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE || + m_type == OBJECT_WORM || + m_type == OBJECT_BULLET ) + { + pyroType = PT_BURNO; + SetBurn(TRUE); + } + else if ( m_type == OBJECT_HUMAN ) + { + pyroType = PT_DEADG; + } + else + { + pyroType = PT_BURNT; + SetBurn(TRUE); + } + SetVirusMode(FALSE); + } + else if ( type == EXPLO_WATER ) + { + if ( m_type == OBJECT_HUMAN ) + { + pyroType = PT_DEADW; + } + else + { + pyroType = PT_FRAGW; + } + } + else // explosion? + { + if ( m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE || + m_type == OBJECT_WORM ) + { + pyroType = PT_EXPLOO; + } + else if ( m_type == OBJECT_MOTHER || + m_type == OBJECT_NEST || + m_type == OBJECT_BULLET ) + { + pyroType = PT_FRAGO; + } + else if ( m_type == OBJECT_HUMAN ) + { + pyroType = PT_DEADG; + } + else if ( m_type == OBJECT_BASE || + m_type == OBJECT_DERRICK || + m_type == OBJECT_FACTORY || + m_type == OBJECT_STATION || + m_type == OBJECT_CONVERT || + m_type == OBJECT_REPAIR || + m_type == OBJECT_DESTROYER|| + m_type == OBJECT_TOWER || + m_type == OBJECT_NEST || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_RADAR || + m_type == OBJECT_INFO || + m_type == OBJECT_ENERGY || + m_type == OBJECT_LABO || + m_type == OBJECT_NUCLEAR || + m_type == OBJECT_PARA || + m_type == OBJECT_SAFE || + m_type == OBJECT_HUSTON || + m_type == OBJECT_START || + m_type == OBJECT_END ) // building? + { + pyroType = PT_FRAGT; + } + else if ( m_type == OBJECT_MOBILEtg || + m_type == OBJECT_TEEN28 || // cylinder? + m_type == OBJECT_TEEN31 ) // basket? + { + pyroType = PT_FRAGT; + } + else + { + pyroType = PT_EXPLOT; + } + } + + loss = 1.0f; + } + + pyro = new CPyro(m_iMan); + pyro->Create(pyroType, this, loss); + + if ( shield == 0.0f ) // dead? + { + if ( m_brain != 0 ) + { + m_brain->StopProgram(); + } + m_main->SaveOneScript(this); + } + + if ( shield > 0.0f ) return FALSE; // not dead yet + + if ( RetSelect() ) + { + SetSelect(FALSE); // deselects the object + m_camera->SetType(CAMERA_EXPLO); + m_main->DeselectAll(); + } + DeleteDeselList(this); + + if ( m_botVar != 0 ) + { + if ( m_type == OBJECT_STONE || + m_type == OBJECT_URANIUM || + m_type == OBJECT_METAL || + m_type == OBJECT_POWER || + m_type == OBJECT_ATOMIC || + m_type == OBJECT_BULLET || + m_type == OBJECT_BBOX || + m_type == OBJECT_TNT || + m_type == OBJECT_SCRAP1 || + m_type == OBJECT_SCRAP2 || + m_type == OBJECT_SCRAP3 || + m_type == OBJECT_SCRAP4 || + m_type == OBJECT_SCRAP5 ) // (*) + { + m_botVar->SetUserPtr(OBJECTDELETED); + } + } + + return TRUE; +} + +// (*) If a robot or cosmonaut dies, the subject must continue to exist, +// so that programs of the ants continue to operate as usual. + + +// Initializes a new part. + +void CObject::InitPart(int part) +{ + m_objectPart[part].bUsed = TRUE; + m_objectPart[part].object = -1; + m_objectPart[part].parentPart = -1; + + m_objectPart[part].position = D3DVECTOR(0.0f, 0.0f, 0.0f); + m_objectPart[part].angle.y = 0.0f; + m_objectPart[part].angle.x = 0.0f; + m_objectPart[part].angle.z = 0.0f; + m_objectPart[part].zoom = D3DVECTOR(1.0f, 1.0f, 1.0f); + + m_objectPart[part].bTranslate = TRUE; + m_objectPart[part].bRotate = TRUE; + m_objectPart[part].bZoom = FALSE; + + D3DUtil_SetIdentityMatrix(m_objectPart[part].matTranslate); + D3DUtil_SetIdentityMatrix(m_objectPart[part].matRotate); + D3DUtil_SetIdentityMatrix(m_objectPart[part].matTransform); + D3DUtil_SetIdentityMatrix(m_objectPart[part].matWorld); + + m_objectPart[part].masterParti = -1; +} + +// Creates a new part, and returns its number. +// Returns -1 on error. + +int CObject::CreatePart() +{ + int i; + + for ( i=0 ; iDeleteParticule(m_objectPart[part].masterParti); + m_objectPart[part].masterParti = -1; + } + + m_objectPart[part].bUsed = FALSE; + m_engine->DeleteObject(m_objectPart[part].object); + UpdateTotalPart(); +} + +void CObject::UpdateTotalPart() +{ + int i; + + m_totalPart = 0; + for ( i=0 ; iSetIdent(m_id); + } +} + +int CObject::RetID() +{ + return m_id; +} + + +// Saves all the parameters of the object. + +BOOL CObject::Write(char *line) +{ + D3DVECTOR pos; + Info info; + char name[100]; + float value; + int i; + + sprintf(name, " camera=%s", GetCamera(RetCameraType())); + strcat(line, name); + + if ( RetCameraLock() != 0 ) + { + sprintf(name, " cameraLock=%d", RetCameraLock()); + strcat(line, name); + } + + if ( RetEnergy() != 0.0f ) + { + sprintf(name, " energy=%.2f", RetEnergy()); + strcat(line, name); + } + + if ( RetCapacity() != 1.0f ) + { + sprintf(name, " capacity=%.2f", RetCapacity()); + strcat(line, name); + } + + if ( RetShield() != 1.0f ) + { + sprintf(name, " shield=%.2f", RetShield()); + strcat(line, name); + } + + if ( RetRange() != 1.0f ) + { + sprintf(name, " range=%.2f", RetRange()); + strcat(line, name); + } + + if ( RetSelectable() != 1 ) + { + sprintf(name, " selectable=%d", RetSelectable()); + strcat(line, name); + } + + if ( RetEnable() != 1 ) + { + sprintf(name, " enable=%d", RetEnable()); + strcat(line, name); + } + + if ( RetFixed() != 0 ) + { + sprintf(name, " fixed=%d", RetFixed()); + strcat(line, name); + } + + if ( RetClip() != 1 ) + { + sprintf(name, " clip=%d", RetClip()); + strcat(line, name); + } + + if ( RetLock() != 0 ) + { + sprintf(name, " lock=%d", RetLock()); + strcat(line, name); + } + + if ( RetProxyActivate() != 0 ) + { + sprintf(name, " proxyActivate=%d", RetProxyActivate()); + strcat(line, name); + + sprintf(name, " proxyDistance=%.2f", RetProxyDistance()/g_unit); + strcat(line, name); + } + + if ( RetMagnifyDamage() != 1.0f ) + { + sprintf(name, " magnifyDamage=%.2f", RetMagnifyDamage()); + strcat(line, name); + } + + if ( RetGunGoalV() != 0.0f ) + { + sprintf(name, " aimV=%.2f", RetGunGoalV()); + strcat(line, name); + } + if ( RetGunGoalH() != 0.0f ) + { + sprintf(name, " aimH=%.2f", RetGunGoalH()); + strcat(line, name); + } + + if ( RetParam() != 0.0f ) + { + sprintf(name, " param=%.2f", RetParam()); + strcat(line, name); + } + + if ( RetResetCap() != 0 ) + { + sprintf(name, " resetCap=%d", RetResetCap()); + strcat(line, name); + + pos = RetResetPosition()/g_unit; + sprintf(name, " resetPos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z); + strcat(line, name); + + pos = RetResetAngle()/(PI/180.0f); + sprintf(name, " resetAngle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z); + strcat(line, name); + + sprintf(name, " resetRun=%d", RetResetRun()); + strcat(line, name); + } + + if ( m_bVirusMode != 0 ) + { + sprintf(name, " virusMode=%d", m_bVirusMode); + strcat(line, name); + } + + if ( m_virusTime != 0.0f ) + { + sprintf(name, " virusTime=%.2f", m_virusTime); + strcat(line, name); + } + + // Puts information in terminal (OBJECT_INFO). + for ( i=0 ; iWrite(line); + } + + if ( m_brain != 0 ) + { + m_brain->Write(line); + } + + if ( m_physics != 0 ) + { + m_physics->Write(line); + } + + if ( m_auto != 0 ) + { + m_auto->Write(line); + } + + return TRUE; +} + +// Returns all parameters of the object. + +BOOL CObject::Read(char *line) +{ + D3DVECTOR pos, dir; + Info info; + CameraType cType; + char op[20]; + char text[100]; + char* p; + float value; + int i; + + cType = OpCamera(line, "camera"); + if ( cType != CAMERA_NULL ) + { + SetCameraType(cType); + } + + SetCameraLock(OpInt(line, "cameraLock", 0)); + SetEnergy(OpFloat(line, "energy", 0.0f)); + SetCapacity(OpFloat(line, "capacity", 1.0f)); + SetShield(OpFloat(line, "shield", 1.0f)); + SetRange(OpFloat(line, "range", 1.0f)); + SetSelectable(OpInt(line, "selectable", 1)); + SetEnable(OpInt(line, "enable", 1)); + SetFixed(OpInt(line, "fixed", 0)); + SetClip(OpInt(line, "clip", 1)); + SetLock(OpInt(line, "lock", 0)); + SetProxyActivate(OpInt(line, "proxyActivate", 0)); + SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit); + SetRange(OpFloat(line, "range", 30.0f)); + SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f)); + SetGunGoalV(OpFloat(line, "aimV", 0.0f)); + SetGunGoalH(OpFloat(line, "aimH", 0.0f)); + SetParam(OpFloat(line, "param", 0.0f)); + SetResetCap((ResetCap)OpInt(line, "resetCap", 0)); + SetResetPosition(OpDir(line, "resetPos")*g_unit); + SetResetAngle(OpDir(line, "resetAngle")*(PI/180.0f)); + SetResetRun(OpInt(line, "resetRun", 0)); + m_bBurn = OpInt(line, "burnMode", 0); + m_bVirusMode = OpInt(line, "virusMode", 0); + m_virusTime = OpFloat(line, "virusTime", 0.0f); + + // Puts information in terminal (OBJECT_INFO). + for ( i=0 ; iReadModel("objects\\convert1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\convert2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(0.0f, 14.0f, 0.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 0); + pModFile->ReadModel("objects\\convert3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(2, D3DVECTOR(0.0f, 11.5f, 0.0f)); + SetAngleX(2, -PI*0.35f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(3, rank); + SetObjectParent(3, 0); + pModFile->ReadModel("objects\\convert3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(3, D3DVECTOR(0.0f, 11.5f, 0.0f)); + SetAngleY(3, PI); + SetAngleX(3, -PI*0.35f); + + m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f); + + CreateCrashSphere(D3DVECTOR(-10.0f, 2.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 2.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 9.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 14.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(-3.0f, 8.0f, 0.0f), 14.0f); + } + + if ( m_type == OBJECT_TOWER ) + { + pModFile->ReadModel("objects\\tower.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\roller2c.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(0.0f, 20.0f, 0.0f)); + SetAngleZ(1, PI/2.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 1); + pModFile->ReadModel("objects\\roller3c.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(2, D3DVECTOR(4.5f, 0.0f, 0.0f)); + SetAngleZ(2, 0.0f); + + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 8.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 15.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 24.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 7.0f); + + m_character.posPower = D3DVECTOR(5.0f, 3.0f, 0.0f); + + CreateShadowCircle(6.0f, 1.0f); + m_showLimitRadius = BLITZPARA; + } + + if ( m_type == OBJECT_NUCLEAR ) + { + pModFile->ReadModel("objects\\nuclear1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\nuclear2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(20.0f, 10.0f, 0.0f)); + SetAngleZ(1, 135.0f*PI/180.0f); + + CreateCrashSphere(D3DVECTOR( 0.0f, 0.0f, 0.0f), 19.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 24.0f, 0.0f), 15.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(22.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 17.0f, 0.0f), 26.0f); + + m_character.posPower = D3DVECTOR(22.0f, 3.0f, 0.0f); + + CreateShadowCircle(21.0f, 1.0f); + } + + if ( m_type == OBJECT_PARA ) + { + pModFile->ReadModel("objects\\para.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + m_terrain->AddBuildingLevel(pos, 16.0f, 18.0f, 1.0f, 0.5f); + + CreateCrashSphere(D3DVECTOR( 13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 11.0f, 15.0f, 11.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 26.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 54.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 20.0f); + + CreateShadowCircle(21.0f, 1.0f); + m_showLimitRadius = BLITZPARA; + } + + if ( m_type == OBJECT_SAFE ) + { + pModFile->ReadModel("objects\\safe1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\safe2.mod"); + pModFile->CreateEngineObject(rank); + SetZoom(1, 1.05f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 0); + pModFile->ReadModel("objects\\safe3.mod"); + pModFile->CreateEngineObject(rank); + SetZoom(2, 1.05f); + + m_terrain->AddBuildingLevel(pos, 18.0f, 20.0f, 1.0f, 0.5f); + + CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 13.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 13.0f); + + CreateShadowCircle(23.0f, 1.0f); + } + + if ( m_type == OBJECT_HUSTON ) + { + pModFile->ReadModel("objects\\huston1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\huston2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(0.0f, 39.0f, 30.0f)); + SetAngleY(1, -PI/2.0f); + SetZoom(1, 3.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 1); + pModFile->ReadModel("objects\\huston3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(2, D3DVECTOR(0.0f, 4.5f, 1.9f)); + + CreateCrashSphere(D3DVECTOR( 15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 27.0f, 30.0f), 12.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 45.0f, 30.0f), 14.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f); + } + + if ( m_type == OBJECT_TARGET1 ) + { + pModFile->ReadModel("objects\\target1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 1.5f); + SetFloorHeight(0.0f); + + CreateCrashSphere(D3DVECTOR( 0.0f, 50.0f+14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 50.0f-14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + + CreateCrashSphere(D3DVECTOR(0.0f, 30.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 24.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 16.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(15.0f, 1.0f); + } + + if ( m_type == OBJECT_TARGET2 ) + { + pModFile->ReadModel("objects\\target2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + height += 50.0f*1.5f; + } + + if ( m_type == OBJECT_NEST ) + { + pModFile->ReadModel("objects\\nest.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + m_terrain->AddBuildingLevel(pos, 3.0f, 5.0f, 1.0f, 0.5f); + + CreateShadowCircle(4.0f, 1.0f); + } + + if ( m_type == OBJECT_START ) + { + pModFile->ReadModel("objects\\start.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f); + } + + if ( m_type == OBJECT_END ) + { + pModFile->ReadModel("objects\\end.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f); + } + +#if 0 + if ( power > 0.0f ) // creates a battery? + { + CObject* pPower; + + pPower = new CObject(m_iMan); + pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + pPower->SetObjectRank(0, rank); + + if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod"); + else pModFile->ReadModel("objects\\atomic.mod"); + pModFile->CreateEngineObject(rank); + + pPower->SetPosition(0, RetCharacter()->posPower); + pPower->CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + pPower->SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.5f); + + pPower->SetTruck(this); + SetPower(pPower); + + if ( power <= 1.0f ) pPower->SetEnergy(power); + else pPower->SetEnergy(power/100.0f); + } +#endif + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); // to display the shadows immediately + + CreateOtherObject(type); + m_engine->LoadAllTexture(); + + delete pModFile; + return TRUE; +} + +// Creates a small resource set on the ground. + +BOOL CObject::CreateResource(D3DVECTOR pos, float angle, ObjectType type, + float power) +{ + CModFile* pModFile; + char name[50]; + int rank; + float radius, height; + + if ( type != OBJECT_SHOW ) + { + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + } + + pModFile = new CModFile(m_iMan); + + SetType(type); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + SetEnergy(power); + + name[0] = 0; + if ( type == OBJECT_STONE ) strcpy(name, "objects\\stone.mod"); + if ( type == OBJECT_URANIUM ) strcpy(name, "objects\\uranium.mod"); + if ( type == OBJECT_METAL ) strcpy(name, "objects\\metal.mod"); + if ( type == OBJECT_POWER ) strcpy(name, "objects\\power.mod"); + if ( type == OBJECT_ATOMIC ) strcpy(name, "objects\\atomic.mod"); + if ( type == OBJECT_BULLET ) strcpy(name, "objects\\bullet.mod"); + if ( type == OBJECT_BBOX ) strcpy(name, "objects\\bbox.mod"); + if ( type == OBJECT_KEYa ) strcpy(name, "objects\\keya.mod"); + if ( type == OBJECT_KEYb ) strcpy(name, "objects\\keyb.mod"); + if ( type == OBJECT_KEYc ) strcpy(name, "objects\\keyc.mod"); + if ( type == OBJECT_KEYd ) strcpy(name, "objects\\keyd.mod"); + if ( type == OBJECT_TNT ) strcpy(name, "objects\\tnt.mod"); + if ( type == OBJECT_SCRAP1 ) strcpy(name, "objects\\scrap1.mod"); + if ( type == OBJECT_SCRAP2 ) strcpy(name, "objects\\scrap2.mod"); + if ( type == OBJECT_SCRAP3 ) strcpy(name, "objects\\scrap3.mod"); + if ( type == OBJECT_SCRAP4 ) strcpy(name, "objects\\scrap4.mod"); + if ( type == OBJECT_SCRAP5 ) strcpy(name, "objects\\scrap5.mod"); + if ( type == OBJECT_BOMB ) strcpy(name, "objects\\bomb.mod"); + if ( type == OBJECT_WAYPOINT ) strcpy(name, "objects\\waypoint.mod"); + if ( type == OBJECT_SHOW ) strcpy(name, "objects\\show.mod"); + if ( type == OBJECT_WINFIRE ) strcpy(name, "objects\\winfire.mod"); + if ( type == OBJECT_BAG ) strcpy(name, "objects\\bag.mod"); + if ( type == OBJECT_MARKSTONE ) strcpy(name, "objects\\cross1.mod"); + if ( type == OBJECT_MARKURANIUM ) strcpy(name, "objects\\cross3.mod"); + if ( type == OBJECT_MARKPOWER ) strcpy(name, "objects\\cross2.mod"); + if ( type == OBJECT_MARKKEYa ) strcpy(name, "objects\\crossa.mod"); + if ( type == OBJECT_MARKKEYb ) strcpy(name, "objects\\crossb.mod"); + if ( type == OBJECT_MARKKEYc ) strcpy(name, "objects\\crossc.mod"); + if ( type == OBJECT_MARKKEYd ) strcpy(name, "objects\\crossd.mod"); + if ( type == OBJECT_EGG ) strcpy(name, "objects\\egg.mod"); + + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + + SetPosition(0, pos); + SetAngleY(0, angle); + + if ( type == OBJECT_SHOW ) // remains in the air? + { + delete pModFile; + return TRUE; + } + + radius = 1.5f; + height = 0.0f; + + if ( type == OBJECT_MARKSTONE || + type == OBJECT_MARKURANIUM || + type == OBJECT_MARKKEYa || + type == OBJECT_MARKKEYb || + type == OBJECT_MARKKEYc || + type == OBJECT_MARKKEYd || + type == OBJECT_MARKPOWER || + type == OBJECT_WAYPOINT ) + { + } + else if ( type == OBJECT_EGG ) + { + CreateCrashSphere(D3DVECTOR(-1.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f); + radius = 3.0f; + } + else if ( type == OBJECT_BOMB ) + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 3.0f); + radius = 3.0f; + } + else if ( type == OBJECT_BAG ) + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f); + SetZoom(0, 1.5f); + radius = 5.0f; + height = -1.4f; + } + else + { + CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 1.5f); + } + CreateShadowCircle(radius, 1.0f); + + SetFloorHeight(0.0f); + CreateOtherObject(type); + m_engine->LoadAllTexture(); + FloorAdjust(); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); // to display the shadows immediately + + delete pModFile; + return TRUE; +} + +// Creates a flag placed on the ground. + +BOOL CObject::CreateFlag(D3DVECTOR pos, float angle, ObjectType type) +{ + CModFile* pModFile; + char name[50]; + int rank, i; + + if ( m_engine->RetRestCreate() < 1+4 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + name[0] = 0; + if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag1b.mod"); + if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag1r.mod"); + if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag1g.mod"); + if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag1y.mod"); + if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag1v.mod"); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + name[0] = 0; + if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag2b.mod"); + if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag2r.mod"); + if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag2g.mod"); + if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag2y.mod"); + if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag2v.mod"); + + for ( i=0 ; i<4 ; i++ ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1+i, rank); + SetObjectParent(1+i, i); + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + if ( i == 0 ) SetPosition(1+i, D3DVECTOR(0.15f, 5.0f, 0.0f)); + else SetPosition(1+i, D3DVECTOR(0.79f, 0.0f, 0.0f)); + } + + SetJotlerSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 1.0f); + CreateShadowCircle(2.0f, 0.3f); + + SetFloorHeight(0.0f); + CreateOtherObject(type); + m_engine->LoadAllTexture(); + FloorAdjust(); + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + delete pModFile; + return TRUE; +} + +// Creates a barrier placed on the ground. + +BOOL CObject::CreateBarrier(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_BARRIER0 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\barrier0.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(6.0f, 0.5f, D3DSHADOWWORM); + } + + if ( type == OBJECT_BARRIER1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\barrier1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(12.0f, 0.5f, D3DSHADOWWORM); + } + + if ( type == OBJECT_BARRIER2 ) // cardboard? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\barrier2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(12.0f, 0.8f, D3DSHADOWWORM); + } + + if ( type == OBJECT_BARRIER3 ) // match + straw? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\barrier3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(10.0f, 0.5f, D3DSHADOWWORM); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + FloorAdjust(); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates a plant placed on the ground. + +BOOL CObject::CreatePlant(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_PLANT0 || + type == OBJECT_PLANT1 || + type == OBJECT_PLANT2 || + type == OBJECT_PLANT3 || + type == OBJECT_PLANT4 ) // standard? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + if ( type == OBJECT_PLANT0 ) pModFile->ReadModel("objects\\plant0.mod"); + if ( type == OBJECT_PLANT1 ) pModFile->ReadModel("objects\\plant1.mod"); + if ( type == OBJECT_PLANT2 ) pModFile->ReadModel("objects\\plant2.mod"); + if ( type == OBJECT_PLANT3 ) pModFile->ReadModel("objects\\plant3.mod"); + if ( type == OBJECT_PLANT4 ) pModFile->ReadModel("objects\\plant4.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + height -= 2.0f; + + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 6.0f); + SetJotlerSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 8.0f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_PLANT5 || + type == OBJECT_PLANT6 || + type == OBJECT_PLANT7 ) // clover? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + if ( type == OBJECT_PLANT5 ) pModFile->ReadModel("objects\\plant5.mod"); + if ( type == OBJECT_PLANT6 ) pModFile->ReadModel("objects\\plant6.mod"); + if ( type == OBJECT_PLANT7 ) pModFile->ReadModel("objects\\plant7.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + +//? CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f); + SetJotlerSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f); + + CreateShadowCircle(5.0f, 0.3f); + } + + if ( type == OBJECT_PLANT8 || + type == OBJECT_PLANT9 ) // squash? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + if ( type == OBJECT_PLANT8 ) pModFile->ReadModel("objects\\plant8.mod"); + if ( type == OBJECT_PLANT9 ) pModFile->ReadModel("objects\\plant9.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + + CreateShadowCircle(10.0f, 0.5f); + } + + if ( type == OBJECT_PLANT10 || + type == OBJECT_PLANT11 || + type == OBJECT_PLANT12 || + type == OBJECT_PLANT13 || + type == OBJECT_PLANT14 ) // succulent? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + if ( type == OBJECT_PLANT10 ) pModFile->ReadModel("objects\\plant10.mod"); + if ( type == OBJECT_PLANT11 ) pModFile->ReadModel("objects\\plant11.mod"); + if ( type == OBJECT_PLANT12 ) pModFile->ReadModel("objects\\plant12.mod"); + if ( type == OBJECT_PLANT13 ) pModFile->ReadModel("objects\\plant13.mod"); + if ( type == OBJECT_PLANT14 ) pModFile->ReadModel("objects\\plant14.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 12.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 6.0f); + SetJotlerSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 8.0f); + + CreateShadowCircle(8.0f, 0.3f); + } + + if ( type == OBJECT_PLANT15 || + type == OBJECT_PLANT16 || + type == OBJECT_PLANT17 || + type == OBJECT_PLANT18 || + type == OBJECT_PLANT19 ) // fern? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + if ( type == OBJECT_PLANT15 ) pModFile->ReadModel("objects\\plant15.mod"); + if ( type == OBJECT_PLANT16 ) pModFile->ReadModel("objects\\plant16.mod"); + if ( type == OBJECT_PLANT17 ) pModFile->ReadModel("objects\\plant17.mod"); + if ( type == OBJECT_PLANT18 ) pModFile->ReadModel("objects\\plant18.mod"); + if ( type == OBJECT_PLANT19 ) pModFile->ReadModel("objects\\plant19.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + if ( type != OBJECT_PLANT19 ) + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 6.0f); + } + SetJotlerSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 8.0f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE0 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree0.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-1.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 0.0f, 17.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 1.0f, 27.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-2.0f, 11.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 2.0f, 26.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 2.0f, 34.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE2 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 0.0f, 3.0f, 1.0f), 3.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-2.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 2.0f, 25.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 3.0f, 32.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE3 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(-2.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-3.0f, 9.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 0.0f, 18.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 0.0f, 27.0f, 7.0f), 2.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE4 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree4.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(0.0f, 21.0f, 0.0f), 8.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(0.0f, 32.0f, 0.0f), 7.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(8.0f, 0.5f); + } + + if ( type == OBJECT_TREE5 ) // giant tree (for the world "teen") + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\tree5.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR( 0.0f, 5.0f,-10.0f), 25.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR(-65.0f, 5.0f, 65.0f), 20.0f, SOUND_BOUMs, 0.20f); + CreateCrashSphere(D3DVECTOR( 38.0f, 5.0f, 21.0f), 18.0f, SOUND_BOUMs, 0.20f); + + CreateShadowCircle(50.0f, 0.5f); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates a mushroom placed on the ground. + +BOOL CObject::CreateMushroom(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_MUSHROOM1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\mush1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 5.5f); + SetJotlerSphere(D3DVECTOR(0.0f, 3.0f, 0.0f), 5.5f); + + CreateShadowCircle(6.0f, 0.5f); + } + + if ( type == OBJECT_MUSHROOM2 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\mush2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 5.5f); + SetJotlerSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 5.5f); + + CreateShadowCircle(5.0f, 0.5f); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates a toy placed on the ground. + +BOOL CObject::CreateTeen(D3DVECTOR pos, float angle, float zoom, float height, + ObjectType type) +{ + CModFile* pModFile; + D3DMATRIX* mat; + D3DCOLORVALUE color; + int rank; + float fShadow; + BOOL bFloorAdjust = TRUE; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + fShadow = Norm(1.0f-height/10.0f); + + if ( type == OBJECT_TEEN0 ) // orange pencil lg=10 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen0.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(5.0f, 0.8f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN1 ) // blue pencil lg=14 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN2 ) // red pencil lg=16 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN3 ) // jar with pencils + { + rank = m_engine->CreateObject(); +//? m_engine->SetObjectType(rank, TYPEFIX); + m_engine->SetObjectType(rank, TYPEMETAL); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 4.0f); + CreateShadowCircle(6.0f, 0.5f*fShadow); + } + + if ( type == OBJECT_TEEN4 ) // scissors + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen4.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-9.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-6.0f, 1.0f, 0.0f), 1.1f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.0f, 1.0f, 0.0f), 1.2f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 1.0f, 0.0f), 1.3f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 5.1f, 1.0f,-1.3f), 2.6f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 8.0f, 1.0f, 2.2f), 2.3f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 9.4f, 1.0f,-2.0f), 2.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(10.0f, 0.5f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN5 ) // CD + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen5.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + SetFloorHeight(0.0f); + bFloorAdjust = FALSE; + + m_terrain->AddBuildingLevel(pos, 5.9f, 6.1f, 0.2f, 0.5f); + CreateShadowCircle(8.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN6 ) // book 1 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen6.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN7 ) // book 2 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen7.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN8 ) // a stack of books 1 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen8.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 12.0f); + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN9 ) // a stack of books 2 + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen9.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 12.0f); + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN10 ) // bookcase + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen10.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-26.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-15.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -4.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -4.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 6.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 6.0f, 3.0f, 4.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 14.0f, 3.0f,-3.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 14.0f, 3.0f, 2.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 24.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 20.0f); + CreateShadowCircle(40.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN11 ) // lamp + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen11.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + SetZoom(0, zoom); + + mat = RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(-56.0f, 22.0f, 0.0f)); + m_particule->CreateParticule(pos, D3DVECTOR(0.0f, 0.0f, 0.0f), FPOINT(20.0f, 20.0f), PARTISELY, 1.0f, 0.0f, 0.0f); + + pos = Transform(*mat, D3DVECTOR(-65.0f, 40.0f, 0.0f)); + color.r = 4.0f; + color.g = 2.0f; + color.b = 0.0f; // yellow-orange + color.a = 0.0f; + m_main->CreateSpot(pos, color); + } + + if ( type == OBJECT_TEEN12 ) // coke + { + rank = m_engine->CreateObject(); +//? m_engine->SetObjectType(rank, TYPEFIX); + m_engine->SetObjectType(rank, TYPEMETAL); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen12.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 9.0f, 0.0f), 5.0f); + CreateShadowCircle(4.5f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN13 ) // cardboard farm + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen13.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 15.0f); + CreateShadowCircle(20.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN14 ) // open box + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen14.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 15.0f); + CreateShadowCircle(20.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN15 ) // stack of cartons + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen15.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 15.0f); + CreateShadowCircle(20.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN16 ) // watering can + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen16.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 13.0f, 0.0f), 20.0f); + CreateShadowCircle(18.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN17 ) // wheel | + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen17.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 31.0f, 0.0f), 31.0f); + CreateShadowCircle(24.0f, 0.5f*fShadow); + } + + if ( type == OBJECT_TEEN18 ) // wheel / + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen18.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 31.0f, 0.0f), 31.0f); + CreateShadowCircle(24.0f, 0.5f*fShadow); + } + + if ( type == OBJECT_TEEN19 ) // wheel = + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen19.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 0.0f, 10.0f, 0.0f), 32.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 32.0f); + CreateShadowCircle(33.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN20 ) // wall with shelf + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen20.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-175.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-175.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -55.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -55.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -37.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -37.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 83.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 83.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + } + + if ( type == OBJECT_TEEN21 ) // wall with window + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen21.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + } + + if ( type == OBJECT_TEEN22 ) // wall with door and shelf + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen22.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-135.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-135.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -15.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -15.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f); + } + + if ( type == OBJECT_TEEN23 ) // skateboard on wheels + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen23.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + if ( m_option == 1 ) // passage under the prohibited skateboard? + { + CreateCrashSphere(D3DVECTOR(-10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f); + } + + CreateCrashSphere(D3DVECTOR(-23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f); + + CreateShadowCircle(35.0f, 0.8f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN24 ) // skate / + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen24.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN25 ) // skate / + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen25.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateShadowCircle(20.0f, 0.2f*fShadow); + } + + if ( type == OBJECT_TEEN26 ) // ceiling lamp + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen26.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + SetFloorHeight(0.0f); + + mat = RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(0.0f, 50.0f, 0.0f)); + m_particule->CreateParticule(pos, D3DVECTOR(0.0f, 0.0f, 0.0f), FPOINT(100.0f, 100.0f), PARTISELY, 1.0f, 0.0f, 0.0f); + + pos = Transform(*mat, D3DVECTOR(0.0f, 50.0f, 0.0f)); + color.r = 4.0f; + color.g = 2.0f; + color.b = 0.0f; // yellow-orange + color.a = 0.0f; + m_main->CreateSpot(pos, color); + } + + if ( type == OBJECT_TEEN27 ) // large plant? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen27.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(40.0f, 0.5f); + } + + if ( type == OBJECT_TEEN28 ) // bottle? + { + rank = m_engine->CreateObject(); +//? m_engine->SetObjectType(rank, TYPEFIX); + m_engine->SetObjectType(rank, TYPEMETAL); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen28.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(7.0f, 0.6f*fShadow); + } + + if ( type == OBJECT_TEEN29 ) // bridge? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen29.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + bFloorAdjust = FALSE; + } + + if ( type == OBJECT_TEEN30 ) // jump? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen30.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 15.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 15.0f, 0.0f), 17.0f); + CreateShadowCircle(20.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN31 ) // basket? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen31.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-10.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 0.0f, 2.0f, 0.0f), 6.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 9.0f, 4.0f, 1.0f), 6.0f, SOUND_BOUM, 0.10f); + + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 10.0f); + CreateShadowCircle(16.0f, 0.6f*fShadow); + } + + if ( type == OBJECT_TEEN32 ) // chair? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen32.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR( 17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR(-17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR(-17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 26.0f); + CreateShadowCircle(35.0f, 0.3f*fShadow); + } + + if ( type == OBJECT_TEEN33 ) // panel? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen33.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(10.0f, 0.3f*fShadow); + } + + if ( type == OBJECT_TEEN34 ) // stone? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen34.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(3.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN35 ) // pipe? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen35.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(-40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR(-20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + CreateCrashSphere(D3DVECTOR( 40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(40.0f, 0.8f*fShadow, D3DSHADOWWORM); + } + + if ( type == OBJECT_TEEN36 ) // trunk? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen36.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + bFloorAdjust = FALSE; + } + + if ( type == OBJECT_TEEN37 ) // boat? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen37.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + bFloorAdjust = FALSE; + } + + if ( type == OBJECT_TEEN38 ) // fan? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen38a.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\teen38b.mod"); // engine + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(0.0f, 30.0f, 0.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 1); + pModFile->ReadModel("objects\\teen38c.mod"); // propeller + pModFile->CreateEngineObject(rank); + SetPosition(2, D3DVECTOR(0.0f, 0.0f, 0.0f)); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 10.0f); + CreateShadowCircle(15.0f, 0.5f*fShadow); + } + + if ( type == OBJECT_TEEN39 ) // potted plant? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen39.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 8.5f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 8.5f); + CreateShadowCircle(10.0f, 1.0f*fShadow); + } + + if ( type == OBJECT_TEEN40 ) // balloon? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen40.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 11.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 14.0f, 0.0f), 15.0f); + CreateShadowCircle(15.0f, 0.7f*fShadow); + } + + if ( type == OBJECT_TEEN41 ) // fence? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen41.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + } + + if ( type == OBJECT_TEEN42 ) // clover? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen42.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(15.0f, 0.4f*fShadow); + } + + if ( type == OBJECT_TEEN43 ) // clover? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen43.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f); + CreateShadowCircle(15.0f, 0.4f*fShadow); + } + + if ( type == OBJECT_TEEN44 ) // car? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\teen44.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, zoom); + + CreateCrashSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 55.0f, SOUND_BOUM, 0.10f); + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 55.0f); + CreateShadowCircle(55.0f, 1.0f*fShadow); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + if ( bFloorAdjust ) + { + SetFloorHeight(0.0f); + FloorAdjust(); + } + + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates a crystal placed on the ground. + +BOOL CObject::CreateQuartz(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + float radius; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_QUARTZ0 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEQUARTZ); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\quartz0.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 3.5f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 3.5f); + + CreateShadowCircle(4.0f, 0.5f); + } + if ( type == OBJECT_QUARTZ1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEQUARTZ); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\quartz1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 5.0f); + + CreateShadowCircle(5.0f, 0.5f); + } + if ( type == OBJECT_QUARTZ2 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEQUARTZ); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\quartz2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 6.0f); + + CreateShadowCircle(6.0f, 0.5f); + } + if ( type == OBJECT_QUARTZ3 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEQUARTZ); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\quartz3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + + CreateCrashSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 10.0f); + + CreateShadowCircle(10.0f, 0.5f); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + if ( type == OBJECT_QUARTZ0 ) + { + pos.y += 4.0f; + radius = 2.0f; + } + if ( type == OBJECT_QUARTZ1 ) + { + pos.y += 6.0f; + radius = 4.0f; + } + if ( type == OBJECT_QUARTZ2 ) + { + pos.y += 10.0f; + radius = 5.0f; + } + if ( type == OBJECT_QUARTZ3 ) + { + pos.y += 16.0f; + radius = 8.0f; + } + m_particule->CreateParticule(pos, pos, FPOINT(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Rand()*0.7f, radius, 0.0f); + m_particule->CreateParticule(pos, pos, FPOINT(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Rand()*0.7f, radius, 0.0f); + + delete pModFile; + return TRUE; +} + +// Creates a root placed on the ground. + +BOOL CObject::CreateRoot(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_ROOT0 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root0.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + CreateCrashSphere(D3DVECTOR(-5.0f, 1.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 4.0f, 1.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 4.0f, 1.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 2.0f, 5.0f, -1.0f), 1.5f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-4.0f, 5.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-2.0f, 8.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 10.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 11.0f); + + CreateShadowCircle(16.0f, 0.5f); + } + if ( type == OBJECT_ROOT1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + CreateCrashSphere(D3DVECTOR(-4.0f, 1.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 1.0f, 2.0f), 1.5f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-2.0f, 5.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 2.0f, 5.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 8.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 12.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 12.0f); + + CreateShadowCircle(16.0f, 0.5f); + } + if ( type == OBJECT_ROOT2 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root2.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + CreateCrashSphere(D3DVECTOR(-3.0f, 1.0f, 0.5f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 1.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-1.0f, 4.5f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 7.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 7.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 4.0f, 11.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 10.0f); + + CreateShadowCircle(16.0f, 0.5f); + } + if ( type == OBJECT_ROOT3 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root3.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + CreateCrashSphere(D3DVECTOR(-4.0f, 1.0f, 1.0f), 3.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 4.0f, 1.0f, -3.0f), 3.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 6.0f, 1.0f, 4.0f), 3.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-2.5f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 4.0f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 6.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 0.0f, 12.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 1.0f, 16.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 10.0f, 0.0f), 14.0f); + + CreateShadowCircle(22.0f, 0.5f); + } + if ( type == OBJECT_ROOT4 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root4.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + CreateCrashSphere(D3DVECTOR( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 12.0f, 0.0f), 20.0f); + + CreateShadowCircle(30.0f, 0.5f); + } + if ( type == OBJECT_ROOT5 ) // gravity root ? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\root4.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 2.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\root5.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(-5.0f, 28.0f, -4.0f)); + SetAngleX(1, -30.0f*PI/180.0f); + SetAngleZ(1, 20.0f*PI/180.0f); + + CreateCrashSphere(D3DVECTOR( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f); + CreateCrashSphere(D3DVECTOR( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 12.0f, 0.0f), 20.0f); + + CreateShadowCircle(30.0f, 0.5f); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates a small home. + +BOOL CObject::CreateHome(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + int rank; + + if ( m_engine->RetRestCreate() < 1 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_HOME1 ) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\home1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 1.3f); + + CreateCrashSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.25f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 6.0f, 0.0f), 11.0f); + CreateShadowCircle(16.0f, 0.5f); + } + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); + + delete pModFile; + return TRUE; +} + +// Creates ruin placed on the ground. + +BOOL CObject::CreateRuin(D3DVECTOR pos, float angle, float height, + ObjectType type) +{ + CModFile* pModFile; + char name[50]; + int rank; + + if ( m_engine->RetRestCreate() < 1+4 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + + name[0] = 0; + if ( type == OBJECT_RUINmobilew1 ) strcpy(name, "objects\\ruin1.mod"); + if ( type == OBJECT_RUINmobilew2 ) strcpy(name, "objects\\ruin1.mod"); + if ( type == OBJECT_RUINmobilet1 ) strcpy(name, "objects\\ruin2.mod"); + if ( type == OBJECT_RUINmobilet2 ) strcpy(name, "objects\\ruin2.mod"); + if ( type == OBJECT_RUINmobiler1 ) strcpy(name, "objects\\ruin3.mod"); + if ( type == OBJECT_RUINmobiler2 ) strcpy(name, "objects\\ruin3.mod"); + if ( type == OBJECT_RUINfactory ) strcpy(name, "objects\\ruin4.mod"); + if ( type == OBJECT_RUINdoor ) strcpy(name, "objects\\ruin5.mod"); + if ( type == OBJECT_RUINsupport ) strcpy(name, "objects\\ruin6.mod"); + if ( type == OBJECT_RUINradar ) strcpy(name, "objects\\ruin7.mod"); + if ( type == OBJECT_RUINconvert ) strcpy(name, "objects\\ruin8.mod"); + if ( type == OBJECT_RUINbase ) strcpy(name, "objects\\ruin9.mod"); + if ( type == OBJECT_RUINhead ) strcpy(name, "objects\\ruin10.mod"); + + pModFile->ReadModel(name); + pModFile->CreateEngineObject(rank); + + SetPosition(0, pos); + SetAngleY(0, angle); + + if ( type == OBJECT_RUINmobilew1 ) // vehicle had wheels? + { + // Creates the right-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(6, rank); + SetObjectParent(6, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(6, D3DVECTOR(-3.0f, 1.8f, -4.0f)); + SetAngleX(6, -PI/2.0f); + + // Creates the left-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(7, rank); + SetObjectParent(7, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(7, D3DVECTOR(-3.0f, 1.0f, 3.0f)); + SetAngleY(7, PI-0.3f); + SetAngleX(7, -0.3f); + + // Creates the right-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(8, rank); + SetObjectParent(8, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(8, D3DVECTOR(2.0f, 1.6f, -3.0f)); + SetAngleY(8, 0.3f); + + // Creates the left-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(9, rank); + SetObjectParent(9, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(9, D3DVECTOR(2.0f, 1.0f, 3.0f)); + SetAngleY(9, PI-0.2f); + SetAngleX(9, 0.2f); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f); + + CreateShadowCircle(4.0f, 1.0f); + } + + if ( type == OBJECT_RUINmobilew2 ) // vehicle has wheels? + { + // Creates the left-back wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(7, rank); + SetObjectParent(7, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(7, D3DVECTOR(-3.0f, 1.0f, 3.0f)); + SetAngleY(7, PI+0.3f); + SetAngleX(7, 0.4f); + + // Creates the left-front wheel. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(9, rank); + SetObjectParent(9, 0); + + pModFile->ReadModel("objects\\ruin1w.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(9, D3DVECTOR(2.0f, 1.0f, 3.0f)); + SetAngleY(9, PI+0.3f); + SetAngleX(9, -0.3f); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f); + + CreateShadowCircle(4.0f, 1.0f); + } + + if ( type == OBJECT_RUINmobilet1 ) // vehicle have caterpillars? + { + // Creates the cannon. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + + pModFile->ReadModel("objects\\ruin2c.mod"); + pModFile->CreateEngineObject(rank); + + SetPosition(1, D3DVECTOR(3.0f, 5.0f, -2.5f)); + SetAngleX(1, -PI*0.85f); + SetAngleY(1, -0.4f); + SetAngleZ(1, -0.1f); + + CreateCrashSphere(D3DVECTOR(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(1.0f, 5.0f, -1.0f), 10.0f); + + CreateShadowCircle(5.0f, 1.0f); + } + + if ( type == OBJECT_RUINmobilet2 ) // vehicle have caterpillars? + { + CreateCrashSphere(D3DVECTOR(0.0f, 2.8f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f); + + CreateShadowCircle(5.0f, 1.0f); + } + + if ( type == OBJECT_RUINmobiler1 ) // vehicle skating? + { + CreateCrashSphere(D3DVECTOR(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(1.0f, 5.0f, -1.0f), 10.0f); + + CreateShadowCircle(5.0f, 1.0f); + } + + if ( type == OBJECT_RUINmobiler2 ) // vehicle skating? + { + CreateCrashSphere(D3DVECTOR(0.0f, 1.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 5.0f, 0.0f), 10.0f); + + CreateShadowCircle(6.0f, 1.0f); + } + + if ( type == OBJECT_RUINfactory ) // factory ? + { + CreateCrashSphere(D3DVECTOR( 9.0f, 1.0f, -11.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 2.0f, -11.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, -10.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-12.0f, 11.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 4.0f, -2.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 8.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 2.0f, 4.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 2.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -4.0f, 0.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 18.0f); + + CreateShadowCircle(20.0f, 0.7f); + } + + if ( type == OBJECT_RUINdoor ) // converter holder? + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 6.0f); + + CreateShadowCircle(6.0f, 1.0f); + } + + if ( type == OBJECT_RUINsupport ) // radar holder? + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 4.0f); + + CreateShadowCircle(3.0f, 1.0f); + } + + if ( type == OBJECT_RUINradar ) // radar base? + { + CreateCrashSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 6.0f); + + CreateShadowCircle(6.0f, 1.0f); + } + + if ( type == OBJECT_RUINconvert ) // converter? + { + m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f); + + CreateCrashSphere(D3DVECTOR(-10.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-10.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f); +//? SetGlobalSphere(D3DVECTOR(-3.0f, 0.0f, 0.0f), 14.0f); + } + + if ( type == OBJECT_RUINbase ) // base? + { + CreateCrashSphere(D3DVECTOR( 0.0f, 15.0f, 0.0f),28.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-42.0f, 6.0f, 17.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-42.0f, 17.0f, 17.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-42.0f, 6.0f, -17.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-42.0f, 17.0f, -17.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-17.0f, 6.0f, -42.0f), 6.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-17.0f, 10.0f, -42.0f), 4.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 15.0f, 13.0f, -34.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 31.0f, 15.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 21.0f, 8.0f, -39.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 26.0f, 8.0f, -33.0f), 5.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 48.0f); + + CreateShadowCircle(40.0f, 1.0f); + } + + if ( type == OBJECT_RUINhead ) // base cap? + { + CreateCrashSphere(D3DVECTOR( 0.0f, 13.0f, 0.0f),20.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, -8.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f,-16.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f,-22.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( -9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f); + SetGlobalSphere(D3DVECTOR(0.0f, 0.0f, 0.0f), 35.0f); + + CreateShadowCircle(30.0f, 1.0f); + } + + pos = RetPosition(0); + SetPosition(0, pos); //to display the shadows immediately + + SetFloorHeight(0.0f); + CreateOtherObject(type); + + if ( type != OBJECT_RUINfactory && + type != OBJECT_RUINconvert && + type != OBJECT_RUINbase ) + { + FloorAdjust(); + } + + pos = RetPosition(0); + pos.y += height; + SetPosition(0, pos); //to display the shadows immediately + + if ( type == OBJECT_RUINmobilew1 ) + { + pos = RetPosition(0); + pos.y -= 0.5f; + SetPosition(0, pos); + + angle = RetAngleX(0)-0.1f; + SetAngleX(0, angle); + } + + if ( type == OBJECT_RUINmobilew2 ) + { + pos = RetPosition(0); + pos.y -= 1.5f; + SetPosition(0, pos); + + angle = RetAngleX(0)-0.9f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)-0.1f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINmobilet1 ) + { + pos = RetPosition(0); + pos.y -= 0.9f; + SetPosition(0, pos); + + angle = RetAngleX(0)-0.3f; + SetAngleX(0, angle); + } + + if ( type == OBJECT_RUINmobilet2 ) + { + pos = RetPosition(0); + pos.y -= 1.5f; + SetPosition(0, pos); + + angle = RetAngleX(0)-0.3f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)+0.8f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINmobiler1 ) + { + pos = RetPosition(0); + pos.y += 4.0f; + SetPosition(0, pos); + + angle = RetAngleX(0)-PI*0.6f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)-0.2f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINmobiler2 ) + { + pos = RetPosition(0); + pos.y += 2.0f; + SetPosition(0, pos); + + angle = RetAngleX(0)-0.1f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)-0.3f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINdoor ) + { + pos = RetPosition(0); + pos.y -= 0.5f; + SetPosition(0, pos); + + angle = RetAngleZ(0)-0.1f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINsupport ) + { + pos = RetPosition(0); + pos.y += 0.5f; + SetPosition(0, pos); + +//? angle = RetAngleY(0)+0.1f; +//? SetAngleY(0, angle); + + angle = RetAngleX(0)+0.1f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)+0.1f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINradar ) + { + pos = RetPosition(0); + pos.y -= 0.5f; + SetPosition(0, pos); + + angle = RetAngleX(0)+0.15f; + SetAngleX(0, angle); + + angle = RetAngleZ(0)+0.1f; + SetAngleZ(0, angle); + } + + if ( type == OBJECT_RUINconvert ) + { + pos = RetPosition(0); + pos.y -= 1.0f; + SetPosition(0, pos); + } + + if ( type == OBJECT_RUINbase ) + { + pos = RetPosition(0); + pos.y -= 1.0f; + SetPosition(0, pos); + + angle = RetAngleX(0)+0.15f; + SetAngleX(0, angle); + } + + if ( type == OBJECT_RUINhead ) + { + pos = RetPosition(0); + pos.y += 8.0f; + SetPosition(0, pos); + + angle = RetAngleX(0)+PI*0.4f; + SetAngleX(0, angle); + } + + delete pModFile; + return TRUE; +} + +// Creates a gadget apollo. + +BOOL CObject::CreateApollo(D3DVECTOR pos, float angle, ObjectType type) +{ + CModFile* pModFile; + int rank, i; + + if ( m_engine->RetRestCreate() < 6 ) return FALSE; + + pModFile = new CModFile(m_iMan); + + SetType(type); + + if ( type == OBJECT_APOLLO1 ) // LEM ? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\apollol1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetZoom(0, 1.2f); + SetFloorHeight(0.0f); + + for ( i=0 ; i<4 ; i++ ) // creates feet + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(i+1, rank); + SetObjectParent(i+1, 0); + pModFile->ReadModel("objects\\apollol2.mod"); + pModFile->CreateEngineObject(rank); + SetAngleY(i+1, PI/2.0f*i); + } + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(5, rank); + SetObjectParent(5, 0); + pModFile->ReadModel("objects\\apollol3.mod"); // ladder + pModFile->CreateEngineObject(rank); + +//? m_terrain->AddBuildingLevel(pos, 10.0f, 13.0f, 12.0f, 0.0f); + + CreateCrashSphere(D3DVECTOR( 0.0f, 4.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 5.0f, -11.0f), 3.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 0.0f, 5.0f, 11.0f), 3.0f, SOUND_BOUMm, 0.45f); + + SetGlobalSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 9.0f); + + CreateShadowCircle(16.0f, 0.5f); + } + + if ( type == OBJECT_APOLLO2 ) // jeep + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); //it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\apolloj1.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + // Wheels. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(-5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(2, rank); + SetObjectParent(2, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + SetPosition(2, D3DVECTOR(-5.75f, 1.65f, 5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(3, rank); + SetObjectParent(3, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + SetPosition(3, D3DVECTOR(5.75f, 1.65f, -5.0f)); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(4, rank); + SetObjectParent(4, 0); + pModFile->ReadModel("objects\\apolloj4.mod"); // wheel + pModFile->CreateEngineObject(rank); + SetPosition(4, D3DVECTOR(5.75f, 1.65f, 5.0f)); + + // Accessories: + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(5, rank); + SetObjectParent(5, 0); + pModFile->ReadModel("objects\\apolloj2.mod"); // antenna + pModFile->CreateEngineObject(rank); + SetPosition(5, D3DVECTOR(5.5f, 8.8f, 2.0f)); + SetAngleY(5, -120.0f*PI/180.0f); + SetAngleZ(5, 45.0f*PI/180.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(6, rank); + SetObjectParent(6, 0); + pModFile->ReadModel("objects\\apolloj3.mod"); // camera + pModFile->CreateEngineObject(rank); + SetPosition(6, D3DVECTOR(5.5f, 2.8f, -2.0f)); + SetAngleY(6, 30.0f*PI/180.0f); + + CreateCrashSphere(D3DVECTOR( 3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR(-3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f); + CreateCrashSphere(D3DVECTOR( 7.0f, 9.0f, 2.0f), 2.0f, SOUND_BOUMm, 0.20f); + + CreateShadowCircle(7.0f, 0.8f); + + FloorAdjust(); + } + + if ( type == OBJECT_APOLLO3 ) // flag? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\apollof.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + SetJotlerSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 1.0f); + CreateShadowCircle(2.0f, 0.3f); + } + + if ( type == OBJECT_APOLLO4 ) // module? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\apollom.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + CreateCrashSphere(D3DVECTOR(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f); + CreateShadowCircle(5.0f, 0.8f); + + FloorAdjust(); + } + + if ( type == OBJECT_APOLLO5 ) // antenna? + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object + SetObjectRank(0, rank); + pModFile->ReadModel("objects\\apolloa.mod"); + pModFile->CreateEngineObject(rank); + SetPosition(0, pos); + SetAngleY(0, angle); + SetFloorHeight(0.0f); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, TYPEDESCENDANT); + SetObjectRank(1, rank); + SetObjectParent(1, 0); + pModFile->ReadModel("objects\\apolloj2.mod"); // antenna + pModFile->CreateEngineObject(rank); + SetPosition(1, D3DVECTOR(0.0f, 5.0f, 0.0f)); + SetAngleY(1, -120.0f*PI/180.0f); + SetAngleZ(1, 45.0f*PI/180.0f); + + CreateCrashSphere(D3DVECTOR(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.35f); + CreateShadowCircle(3.0f, 0.7f); + } + + CreateOtherObject(type); + + pos = RetPosition(0); + SetPosition(0, pos); // to display the shadows immediately + + delete pModFile; + return TRUE; +} + +// Creates all sub-objects for managing the object. + +void CObject::CreateOtherObject(ObjectType type) +{ + if ( type == OBJECT_BASE ) + { + m_auto = new CAutoBase(m_iMan, this); + } + if ( type == OBJECT_PORTICO ) + { + m_auto = new CAutoPortico(m_iMan, this); + } + if ( type == OBJECT_DERRICK ) + { + m_auto = new CAutoDerrick(m_iMan, this); + } + if ( type == OBJECT_FACTORY ) + { + m_auto = new CAutoFactory(m_iMan, this); + } + if ( type == OBJECT_REPAIR ) + { + m_auto = new CAutoRepair(m_iMan, this); + } + if ( type == OBJECT_DESTROYER ) + { + m_auto = new CAutoDestroyer(m_iMan, this); + } + if ( type == OBJECT_STATION ) + { + m_auto = new CAutoStation(m_iMan, this); + } + if ( type == OBJECT_CONVERT ) + { + m_auto = new CAutoConvert(m_iMan, this); + } + if ( type == OBJECT_TOWER ) + { + m_auto = new CAutoTower(m_iMan, this); + } + if ( type == OBJECT_RESEARCH ) + { + m_auto = new CAutoResearch(m_iMan, this); + } + if ( type == OBJECT_RADAR ) + { + m_auto = new CAutoRadar(m_iMan, this); + } + if ( type == OBJECT_INFO ) + { + m_auto = new CAutoInfo(m_iMan, this); + } + if ( type == OBJECT_ENERGY ) + { + m_auto = new CAutoEnergy(m_iMan, this); + } + if ( type == OBJECT_LABO ) + { + m_auto = new CAutoLabo(m_iMan, this); + } + if ( type == OBJECT_NUCLEAR ) + { + m_auto = new CAutoNuclear(m_iMan, this); + } + if ( type == OBJECT_PARA ) + { + m_auto = new CAutoPara(m_iMan, this); + } + if ( type == OBJECT_SAFE ) + { + m_auto = new CAutoSafe(m_iMan, this); + } + if ( type == OBJECT_HUSTON ) + { + m_auto = new CAutoHuston(m_iMan, this); + } + if ( type == OBJECT_EGG ) + { + m_auto = new CAutoEgg(m_iMan, this); + } + if ( type == OBJECT_NEST ) + { + m_auto = new CAutoNest(m_iMan, this); + } + if ( type == OBJECT_ROOT5 ) + { + m_auto = new CAutoRoot(m_iMan, this); + } + if ( type == OBJECT_MUSHROOM2 ) + { + m_auto = new CAutoMush(m_iMan, this); + } + if ( type == OBJECT_FLAGb || + type == OBJECT_FLAGr || + type == OBJECT_FLAGg || + type == OBJECT_FLAGy || + type == OBJECT_FLAGv ) + { + m_auto = new CAutoFlag(m_iMan, this); + } + if ( type == OBJECT_TEEN36 || // trunk? + type == OBJECT_TEEN37 || // boat? + type == OBJECT_TEEN38 ) // fan? + { + m_auto = new CAutoKid(m_iMan, this); + } +} + + +// Reads a program. + +BOOL CObject::ReadProgram(int rank, char* filename) +{ + if ( m_brain != 0 ) + { + return m_brain->ReadProgram(rank, filename); + } + return FALSE; +} + +// Writes a program. + +BOOL CObject::WriteProgram(int rank, char* filename) +{ + if ( m_brain != 0 ) + { + return m_brain->WriteProgram(rank, filename); + } + return FALSE; +} + +// Starts a program. + +BOOL CObject::RunProgram(int rank) +{ + if ( m_brain != 0 ) + { + m_brain->RunProgram(rank); + return TRUE; + } + if ( m_auto != 0 ) + { + m_auto->Start(rank); + return TRUE; + } + return FALSE; +} + + + + +// Calculates the matrix for transforming the object. +// Returns TRUE if the matrix has changed. +// The rotations occur in the order Y, Z and X. + +BOOL CObject::UpdateTransformObject(int part, BOOL bForceUpdate) +{ + D3DVECTOR position, angle, eye; + BOOL bModif = FALSE; + int parent; + + if ( m_truck != 0 ) // transported by truck? + { + m_objectPart[part].bTranslate = TRUE; + m_objectPart[part].bRotate = TRUE; + } + + if ( !bForceUpdate && + !m_objectPart[part].bTranslate && + !m_objectPart[part].bRotate ) return FALSE; + + position = m_objectPart[part].position; + angle = m_objectPart[part].angle; + + if ( part == 0 ) // main part? + { + position += m_linVibration; + angle += m_cirVibration+m_inclinaison; + } + + if ( m_objectPart[part].bTranslate || + m_objectPart[part].bRotate ) + { + if ( m_objectPart[part].bTranslate ) + { + D3DUtil_SetIdentityMatrix(m_objectPart[part].matTranslate); + m_objectPart[part].matTranslate._41 = position.x; + m_objectPart[part].matTranslate._42 = position.y; + m_objectPart[part].matTranslate._43 = position.z; + } + + if ( m_objectPart[part].bRotate ) + { + MatRotateZXY(m_objectPart[part].matRotate, angle); + } + + if ( m_objectPart[part].bZoom ) + { + D3DMATRIX mz; + D3DUtil_SetIdentityMatrix(mz); + mz._11 = m_objectPart[part].zoom.x; + mz._22 = m_objectPart[part].zoom.y; + mz._33 = m_objectPart[part].zoom.z; + m_objectPart[part].matTransform = mz * + m_objectPart[part].matRotate * + m_objectPart[part].matTranslate; + } + else + { + m_objectPart[part].matTransform = m_objectPart[part].matRotate * + m_objectPart[part].matTranslate; + } + bModif = TRUE; + } + + if ( bForceUpdate || + m_objectPart[part].bTranslate || + m_objectPart[part].bRotate ) + { + parent = m_objectPart[part].parentPart; + + if ( part == 0 && m_truck != 0 ) // transported by a truck? + { + D3DMATRIX* matWorldTruck; + matWorldTruck = m_truck->RetWorldMatrix(m_truckLink); + m_objectPart[part].matWorld = m_objectPart[part].matTransform * + *matWorldTruck; + } + else + { + if ( parent == -1 ) // no parent? + { + m_objectPart[part].matWorld = m_objectPart[part].matTransform; + } + else + { + m_objectPart[part].matWorld = m_objectPart[part].matTransform * + m_objectPart[parent].matWorld; + } + } + bModif = TRUE; + } + + if ( bModif ) + { + m_engine->SetObjectTransform(m_objectPart[part].object, + m_objectPart[part].matWorld); + } + + m_objectPart[part].bTranslate = FALSE; + m_objectPart[part].bRotate = FALSE; + + return bModif; +} + +// Updates all matrices to transform the object father and all his sons. +// Assume a maximum of 4 degrees of freedom. +// Appropriate, for example, to a body, an arm, forearm, hand and fingers. + +BOOL CObject::UpdateTransformObject() +{ + BOOL bUpdate1, bUpdate2, bUpdate3, bUpdate4; + int level1, level2, level3, level4, rank; + int parent1, parent2, parent3, parent4; + + if ( m_bFlat ) + { + for ( level1=0 ; level1RetLimitLOD(0); + limit[2] = limit[1]; + limit[3] = m_engine->RetLimitLOD(1); + limit[4] = limit[3]; + limit[5] = 1000000.0f; + + for ( j=0 ; j<3 ; j++ ) + { + m_engine->ChangeTextureMapping(m_objectPart[0].object, + mat, D3DSTATEPART3, "lemt.tga", "", + limit[j*2+0], limit[j*2+1], D3DMAPPING1Y, + au, bu, 1.0f, 0.0f); + } +} + + +// Manual action. + +BOOL CObject::EventProcess(const Event &event) +{ + if ( event.event == EVENT_KEYDOWN ) + { +#if ADJUST_ONBOARD + if ( m_bSelect ) + { + if ( event.param == 'E' ) debug_x += 0.1f; + if ( event.param == 'D' ) debug_x -= 0.1f; + if ( event.param == 'R' ) debug_y += 0.1f; + if ( event.param == 'F' ) debug_y -= 0.1f; + if ( event.param == 'T' ) debug_z += 0.1f; + if ( event.param == 'G' ) debug_z -= 0.1f; + } +#endif +#if ADJUST_ARM + if ( m_bSelect ) + { + if ( event.param == 'X' ) debug_arm1 += 5.0f*PI/180.0f; + if ( event.param == 'C' ) debug_arm1 -= 5.0f*PI/180.0f; + if ( event.param == 'V' ) debug_arm2 += 5.0f*PI/180.0f; + if ( event.param == 'B' ) debug_arm2 -= 5.0f*PI/180.0f; + if ( event.param == 'N' ) debug_arm3 += 5.0f*PI/180.0f; + if ( event.param == 'M' ) debug_arm3 -= 5.0f*PI/180.0f; + if ( event.param == 'X' || + event.param == 'C' || + event.param == 'V' || + event.param == 'B' || + event.param == 'N' || + event.param == 'M' ) + { + SetAngleZ(1, debug_arm1); + SetAngleZ(2, debug_arm2); + SetAngleZ(3, debug_arm3); + char s[100]; + sprintf(s, "a=%.2f b=%.2f c=%.2f", debug_arm1*180.0f/PI, debug_arm2*180.0f/PI, debug_arm3*180.0f/PI); + m_engine->SetInfoText(5, s); + } + } +#endif + } + + if ( m_physics != 0 ) + { + if ( !m_physics->EventProcess(event) ) // object destroyed? + { + if ( RetSelect() && + m_type != OBJECT_ANT && + m_type != OBJECT_SPIDER && + m_type != OBJECT_BEE ) + { + if ( !m_bDead ) m_camera->SetType(CAMERA_EXPLO); + m_main->DeselectAll(); + } + return FALSE; + } + } + + if ( m_auto != 0 ) + { + m_auto->EventProcess(event); + + if ( event.event == EVENT_FRAME && + m_auto->IsEnded() != ERR_CONTINUE ) + { + m_auto->DeleteObject(); + delete m_auto; + m_auto = 0; + } + } + + if ( m_motion != 0 ) + { + m_motion->EventProcess(event); + } + + if ( event.event == EVENT_FRAME ) + { + return EventFrame(event); + } + + return TRUE; +} + + +// Animates the object. + +BOOL CObject::EventFrame(const Event &event) +{ + if ( m_type == OBJECT_HUMAN && m_main->RetMainMovie() == MM_SATCOMopen ) + { + UpdateTransformObject(); + return TRUE; + } + + if ( m_type != OBJECT_SHOW && m_engine->RetPause() ) return TRUE; + + m_aTime += event.rTime; + m_shotTime += event.rTime; + + VirusFrame(event.rTime); + PartiFrame(event.rTime); + + UpdateMapping(); + UpdateTransformObject(); + UpdateSelectParticule(); + + if ( m_bProxyActivate ) // active if it is near? + { + CPyro* pyro; + D3DVECTOR eye; + float dist; + + eye = m_engine->RetLookatPt(); + dist = Length(eye, RetPosition(0)); + if ( dist < m_proxyDistance ) + { + m_bProxyActivate = FALSE; + m_main->CreateShortcuts(); + m_sound->Play(SOUND_FINDING); + pyro = new CPyro(m_iMan); + pyro->Create(PT_FINDING, this, 0.0f); + m_displayText->DisplayError(INFO_FINDING, this); + } + } + + return TRUE; +} + +// Updates the mapping of the object. + +void CObject::UpdateMapping() +{ + if ( m_type == OBJECT_POWER || + m_type == OBJECT_ATOMIC || + m_type == OBJECT_STATION || + m_type == OBJECT_ENERGY ) + { + UpdateEnergyMapping(); + } +} + + +// Management of viruses. + +void CObject::VirusFrame(float rTime) +{ + ParticuleType type; + D3DVECTOR pos, speed; + FPOINT dim; + int r; + + if ( !m_bVirusMode ) return; // healthy object? + + m_virusTime += rTime; + if ( m_virusTime >= VIRUS_DELAY ) + { + m_bVirusMode = FALSE; // the virus is no longer active + } + + if ( m_lastVirusParticule+m_engine->ParticuleAdapt(0.2f) <= m_aTime ) + { + m_lastVirusParticule = m_aTime; + + r = rand()%10; + if ( r == 0 ) type = PARTIVIRUS1; + if ( r == 1 ) type = PARTIVIRUS2; + if ( r == 2 ) type = PARTIVIRUS3; + if ( r == 3 ) type = PARTIVIRUS4; + if ( r == 4 ) type = PARTIVIRUS5; + if ( r == 5 ) type = PARTIVIRUS6; + if ( r == 6 ) type = PARTIVIRUS7; + if ( r == 7 ) type = PARTIVIRUS8; + if ( r == 8 ) type = PARTIVIRUS9; + if ( r == 9 ) type = PARTIVIRUS10; + + pos = RetPosition(0); + pos.x += (Rand()-0.5f)*10.0f; + pos.z += (Rand()-0.5f)*10.0f; + speed.x = (Rand()-0.5f)*2.0f; + speed.z = (Rand()-0.5f)*2.0f; + speed.y = Rand()*4.0f+4.0f; + dim.x = Rand()*0.3f+0.3f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, type, 3.0f); + } +} + +// Management particles mistresses. + +void CObject::PartiFrame(float rTime) +{ + D3DVECTOR pos, angle, factor; + int i, channel; + + for ( i=0 ; iGetPosition(channel, pos) ) + { + m_objectPart[i].masterParti = -1; // particle no longer exists! + continue; + } + + SetPosition(i, pos); + + // Each song spins differently. + switch( i%5 ) + { + case 0: factor = D3DVECTOR( 0.5f, 0.3f, 0.6f); break; + case 1: factor = D3DVECTOR(-0.3f, 0.4f,-0.2f); break; + case 2: factor = D3DVECTOR( 0.4f,-0.6f,-0.3f); break; + case 3: factor = D3DVECTOR(-0.6f,-0.2f, 0.0f); break; + case 4: factor = D3DVECTOR( 0.4f, 0.1f,-0.7f); break; + } + + angle = RetAngle(i); + angle += rTime*PI*factor; + SetAngle(i, angle); + } +} + + +// Changes the perspective to view if it was like in the vehicle, +// or behind the vehicle. + +void CObject::SetViewFromHere(D3DVECTOR &eye, float &dirH, float &dirV, + D3DVECTOR &lookat, D3DVECTOR &upVec, + CameraType type) +{ + float speed; + int part; + + UpdateTransformObject(); + + part = 0; + if ( m_type == OBJECT_HUMAN || + m_type == OBJECT_TECH ) + { + eye.x = -0.2f; + eye.y = 3.3f; + eye.z = 0.0f; +//? eye.x = 1.0f; +//? eye.y = 3.3f; +//? eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) + { + eye.x = -1.1f; // on the cap + eye.y = 7.9f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEic ) // fireball? + { +//? eye.x = -0.9f; // on the cannon +//? eye.y = 3.0f; +//? eye.z = 0.0f; +//? part = 1; + eye.x = -0.9f; // on the cannon + eye.y = 8.3f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEii ) // orgaball ? + { +//? eye.x = -3.5f; // on the cannon +//? eye.y = 5.1f; +//? eye.z = 0.0f; +//? part = 1; + eye.x = -2.5f; // on the cannon + eye.y = 10.4f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILErc ) + { +//? eye.x = 2.0f; // in the cannon +//? eye.y = 0.0f; +//? eye.z = 0.0f; +//? part = 2; + eye.x = 4.0f; // on the cannon + eye.y = 11.0f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILEsa ) + { + eye.x = 3.0f; + eye.y = 4.5f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_MOBILEdr ) + { + eye.x = 1.0f; + eye.y = 6.5f; + eye.z = 0.0f; + } + else if ( m_type == OBJECT_APOLLO2 ) + { + eye.x = -3.0f; + eye.y = 6.0f; + eye.z = -2.0f; + } + else + { + eye.x = 0.7f; // between the brackets + eye.y = 4.8f; + eye.z = 0.0f; + } +#if ADJUST_ONBOARD + eye.x += debug_x; + eye.y += debug_y; + eye.z += debug_z; + char s[100]; + sprintf(s, "x=%.2f y=%.2f z=%.2f", eye.x, eye.y, eye.z); + m_engine->SetInfoText(4, s); +#endif + + if ( type == CAMERA_BACK ) + { + eye.x -= 20.0f; + eye.y += 1.0f; + } + + lookat.x = eye.x+1.0f; + lookat.y = eye.y+0.0f; + lookat.z = eye.z+0.0f; + + eye = Transform(m_objectPart[part].matWorld, eye); + lookat = Transform(m_objectPart[part].matWorld, lookat); + + // Camera tilts when turning. + upVec = D3DVECTOR(0.0f, 1.0f, 0.0f); + if ( m_physics != 0 ) + { + if ( m_physics->RetLand() ) // on ground? + { + speed = m_physics->RetLinMotionX(MO_REASPEED); + lookat.y -= speed*0.002f; + + speed = m_physics->RetCirMotionY(MO_REASPEED); + upVec.z -= speed*0.04f; + } + else // in flight? + { + speed = m_physics->RetLinMotionX(MO_REASPEED); + lookat.y += speed*0.002f; + + speed = m_physics->RetCirMotionY(MO_REASPEED); + upVec.z += speed*0.08f; + } + } + upVec = Transform(m_objectPart[0].matRotate, upVec); + + dirH = -(m_objectPart[part].angle.y+PI/2.0f); + dirV = 0.0f; + +} + + +// Management of features. + +void CObject::SetCharacter(Character* character) +{ + CopyMemory(&m_character, character, sizeof(Character)); +} + +void CObject::GetCharacter(Character* character) +{ + CopyMemory(character, &m_character, sizeof(Character)); +} + +Character* CObject::RetCharacter() +{ + return &m_character; +} + + +// Returns the absolute time. + +float CObject::RetAbsTime() +{ + return m_aTime; +} + + +// Management of energy contained in a battery. +// Single subject possesses the battery energy, but not the vehicle that carries the battery! + +void CObject::SetEnergy(float level) +{ + if ( level < 0.0f ) level = 0.0f; + if ( level > 1.0f ) level = 1.0f; + m_energy = level; +} + +float CObject::RetEnergy() +{ + if ( m_type != OBJECT_POWER && + m_type != OBJECT_ATOMIC && + m_type != OBJECT_STATION && + m_type != OBJECT_ENERGY ) return 0.0f; + return m_energy; +} + + +// Management of the capacity of a battery. +// Single subject possesses a battery capacity, +// but not the vehicle that carries the battery! + +void CObject::SetCapacity(float capacity) +{ + m_capacity = capacity; +} + +float CObject::RetCapacity() +{ + return m_capacity; +} + + +// Management of the shield. + +void CObject::SetShield(float level) +{ + m_shield = level; +} + +float CObject::RetShield() +{ + if ( m_type == OBJECT_FRET || + m_type == OBJECT_STONE || + m_type == OBJECT_URANIUM || + m_type == OBJECT_BULLET || + m_type == OBJECT_METAL || + m_type == OBJECT_BBOX || + m_type == OBJECT_KEYa || + m_type == OBJECT_KEYb || + m_type == OBJECT_KEYc || + m_type == OBJECT_KEYd || + m_type == OBJECT_TNT || + m_type == OBJECT_TEEN31 || // basket? + m_type == OBJECT_SCRAP1 || + m_type == OBJECT_SCRAP2 || + m_type == OBJECT_SCRAP3 || + m_type == OBJECT_SCRAP4 || + m_type == OBJECT_SCRAP5 || + m_type == OBJECT_BOMB || + m_type == OBJECT_WAYPOINT || + m_type == OBJECT_FLAGb || + m_type == OBJECT_FLAGr || + m_type == OBJECT_FLAGg || + m_type == OBJECT_FLAGy || + m_type == OBJECT_FLAGv || + m_type == OBJECT_POWER || + m_type == OBJECT_ATOMIC || + m_type == OBJECT_ANT || + m_type == OBJECT_SPIDER || + m_type == OBJECT_BEE || + m_type == OBJECT_WORM ) return 0.0f; + return m_shield; +} + + +// Management of flight range (zero = infinity). + +void CObject::SetRange(float delay) +{ + m_range = delay; +} + +float CObject::RetRange() +{ + return m_range; +} + + +// Management of transparency of the object. + +void CObject::SetTransparency(float value) +{ + int i; + + m_transparency = value; + + for ( i=0 ; iSetObjectTransparency(m_objectPart[i].object, value); + } + } +} + +float CObject::RetTransparency() +{ + return m_transparency; +} + + +// Management of the object matter. + +ObjectMaterial CObject::RetMaterial() +{ + if ( m_type == OBJECT_HUMAN ) + { + return OM_HUMAN; + } + + if ( m_type == OBJECT_SCRAP4 || + m_type == OBJECT_SCRAP5 ) + { + return OM_HUMAN; + } + + return OM_METAL; +} + + +// Indicates whether the gadget is a nonessential. + +void CObject::SetGadget(BOOL bMode) +{ + m_bGadget = bMode; +} + +BOOL CObject::RetGadget() +{ + return m_bGadget; +} + + +// Indicates whether an object is stationary (ant on the back). + +void CObject::SetFixed(BOOL bFixed) +{ + m_bFixed = bFixed; +} + +BOOL CObject::RetFixed() +{ + return m_bFixed; +} + + +// Indicates whether an object is subjected to clipping (obstacles). + +void CObject::SetClip(BOOL bClip) +{ + m_bClip = bClip; +} + +BOOL CObject::RetClip() +{ + return m_bClip; +} + + + +// Pushes an object. + +BOOL CObject::JostleObject(float force) +{ + CAutoJostle* pa; + + if ( m_type == OBJECT_FLAGb || + m_type == OBJECT_FLAGr || + m_type == OBJECT_FLAGg || + m_type == OBJECT_FLAGy || + m_type == OBJECT_FLAGv ) // flag? + { + if ( m_auto == 0 ) return FALSE; + + m_auto->Start(1); + } + else + { + if ( m_auto != 0 ) return FALSE; + + m_auto = new CAutoJostle(m_iMan, this); + pa = (CAutoJostle*)m_auto; + pa->Start(0, force); + } + + return TRUE; +} + + +// Beginning of the effect when the instruction "detect" is used. + +void CObject::StartDetectEffect(CObject *target, BOOL bFound) +{ + D3DMATRIX* mat; + D3DVECTOR pos, goal; + FPOINT dim; + + mat = RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(2.0f, 3.0f, 0.0f)); + + if ( target == 0 ) + { + goal = Transform(*mat, D3DVECTOR(50.0f, 3.0f, 0.0f)); + } + else + { + goal = target->RetPosition(0); + goal.y += 3.0f; + goal = SegmentDist(pos, goal, Length(pos, goal)-3.0f); + } + + dim.x = 3.0f; + dim.y = dim.x; + m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.2f); + + if ( target != 0 ) + { + goal = target->RetPosition(0); + goal.y += 3.0f; + goal = SegmentDist(pos, goal, Length(pos, goal)-1.0f); + dim.x = 6.0f; + dim.y = dim.x; + m_particule->CreateParticule(goal, D3DVECTOR(0.0f, 0.0f, 0.0f), dim, + bFound?PARTIGLINT:PARTIGLINTr, 0.5f); + } + + m_sound->Play(bFound?SOUND_BUILD:SOUND_RECOVER); +} + + +// Management of time from which a virus is active. + +void CObject::SetVirusMode(BOOL bEnable) +{ + m_bVirusMode = bEnable; + m_virusTime = 0.0f; + + if ( m_bVirusMode && m_brain != 0 ) + { + if ( !m_brain->IntroduceVirus() ) // tries to infect + { + m_bVirusMode = FALSE; // program was not contaminated! + } + } +} + +BOOL CObject::RetVirusMode() +{ + return m_bVirusMode; +} + +float CObject::RetVirusTime() +{ + return m_virusTime; +} + + +// Management mode of the camera. + +void CObject::SetCameraType(CameraType type) +{ + m_cameraType = type; +} + +CameraType CObject::RetCameraType() +{ + return m_cameraType; +} + +void CObject::SetCameraDist(float dist) +{ + m_cameraDist = dist; +} + +float CObject::RetCameraDist() +{ + return m_cameraDist; +} + +void CObject::SetCameraLock(BOOL bLock) +{ + m_bCameraLock = bLock; +} + +BOOL CObject::RetCameraLock() +{ + return m_bCameraLock; +} + + + +// Management of the demonstration of the object. + +void CObject::SetHilite(BOOL bMode) +{ + int list[OBJECTMAXPART+1]; + int i, j; + + m_bHilite = bMode; + + if ( m_bHilite ) + { + j = 0; + for ( i=0 ; iSetHiliteRank(list); // gives the list of selected parts + } +} + +BOOL CObject::RetHilite() +{ + return m_bHilite; +} + + +// Indicates whether the object is selected or not. + +void CObject::SetSelect(BOOL bMode, BOOL bDisplayError) +{ + Error err; + + m_bSelect = bMode; + + if ( m_physics != 0 ) + { + m_physics->CreateInterface(m_bSelect); + } + + if ( m_auto != 0 ) + { + m_auto->CreateInterface(m_bSelect); + } + + CreateSelectParticule(); // creates / removes particles + + if ( !m_bSelect ) + { + SetGunGoalH(0.0f); // puts the cannon right + return; // selects if not finished + } + + err = ERR_OK; + if ( m_physics != 0 ) + { + err = m_physics->RetError(); + } + if ( m_auto != 0 ) + { + err = m_auto->RetError(); + } + if ( err != ERR_OK && bDisplayError ) + { + m_displayText->DisplayError(err, this); + } +} + +// Indicates whether the object is selected or not. + +BOOL CObject::RetSelect(BOOL bReal) +{ + if ( !bReal && m_main->RetFixScene() ) return FALSE; + return m_bSelect; +} + + +// Indicates whether the object is selectable or not. + +void CObject::SetSelectable(BOOL bMode) +{ + m_bSelectable = bMode; +} + +// Indicates whether the object is selecionnable or not. + +BOOL CObject::RetSelectable() +{ + return m_bSelectable; +} + + +// Management of the activities of an object. + +void CObject::SetActivity(BOOL bMode) +{ + if ( m_brain != 0 ) + { + m_brain->SetActivity(bMode); + } +} + +BOOL CObject::RetActivity() +{ + if ( m_brain != 0 ) + { + return m_brain->RetActivity(); + } + return FALSE; +} + + +// Indicates if necessary to check the tokens of the object. + +void CObject::SetCheckToken(BOOL bMode) +{ + m_bCheckToken = bMode; +} + +// Indicates if necessary to check the tokens of the object. + +BOOL CObject::RetCheckToken() +{ + return m_bCheckToken; +} + + +// Management of the visibility of an object. +// The object is not hidden or visually disabled, but ignores detections! +// For example: underground worm. + +void CObject::SetVisible(BOOL bVisible) +{ + m_bVisible = bVisible; +} + +BOOL CObject::RetVisible() +{ + return m_bVisible; +} + + +// Management mode of operation of an object. +// An inactive object is an object destroyed, nonexistent. +// This mode is used for objects "resetables" +// during training to simulate destruction. + +void CObject::SetEnable(BOOL bEnable) +{ + m_bEnable = bEnable; +} + +BOOL CObject::RetEnable() +{ + return m_bEnable; +} + + +// Management mode or an object is only active when you're close. + +void CObject::SetProxyActivate(BOOL bActivate) +{ + m_bProxyActivate = bActivate; +} + +BOOL CObject::RetProxyActivate() +{ + return m_bProxyActivate; +} + +void CObject::SetProxyDistance(float distance) +{ + m_proxyDistance = distance; +} + +float CObject::RetProxyDistance() +{ + return m_proxyDistance; +} + + +// Management of the method of increasing damage. + +void CObject::SetMagnifyDamage(float factor) +{ + m_magnifyDamage = factor; +} + +float CObject::RetMagnifyDamage() +{ + return m_magnifyDamage; +} + + +// Management of free parameter. + +void CObject::SetParam(float value) +{ + m_param = value; +} + +float CObject::RetParam() +{ + return m_param; +} + + +// Management of the mode "blocked" of an object. +// For example, a cube of titanium is blocked while it is used to make something, +//or a vehicle is blocked as its construction is not finished. + +void CObject::SetLock(BOOL bLock) +{ + m_bLock = bLock; +} + +BOOL CObject::RetLock() +{ + return m_bLock; +} + +// Management of the mode "current explosion" of an object. +// An object in this mode is not saving. + +void CObject::SetExplo(BOOL bExplo) +{ + m_bExplo = bExplo; +} + +BOOL CObject::RetExplo() +{ + return m_bExplo; +} + + +// Mode management "cargo ship" during movies. + +void CObject::SetCargo(BOOL bCargo) +{ + m_bCargo = bCargo; +} + +BOOL CObject::RetCargo() +{ + return m_bCargo; +} + + +// Management of the HS mode of an object. + +void CObject::SetBurn(BOOL bBurn) +{ + m_bBurn = bBurn; + +//? if ( m_botVar != 0 ) +//? { +//? if ( m_bBurn ) m_botVar->SetUserPtr(OBJECTDELETED); +//? else m_botVar->SetUserPtr(this); +//? } +} + +BOOL CObject::RetBurn() +{ + return m_bBurn; +} + +void CObject::SetDead(BOOL bDead) +{ + m_bDead = bDead; + + if ( bDead && m_brain != 0 ) + { + m_brain->StopProgram(); // stops the current task + } + +//? if ( m_botVar != 0 ) +//? { +//? if ( m_bDead ) m_botVar->SetUserPtr(OBJECTDELETED); +//? else m_botVar->SetUserPtr(this); +//? } +} + +BOOL CObject::RetDead() +{ + return m_bDead; +} + +BOOL CObject::RetRuin() +{ + return m_bBurn|m_bFlat; +} + +BOOL CObject::RetActif() +{ + return !m_bLock && !m_bBurn && !m_bFlat && m_bVisible && m_bEnable; +} + + +// Management of the point of aim. + +void CObject::SetGunGoalV(float gunGoal) +{ + if ( m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEic ) // fireball? + { + if ( gunGoal > 10.0f*PI/180.0f ) gunGoal = 10.0f*PI/180.0f; + if ( gunGoal < -20.0f*PI/180.0f ) gunGoal = -20.0f*PI/180.0f; + SetAngleZ(1, gunGoal); + } + else if ( m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEii ) // orgaball? + { + if ( gunGoal > 20.0f*PI/180.0f ) gunGoal = 20.0f*PI/180.0f; + if ( gunGoal < -20.0f*PI/180.0f ) gunGoal = -20.0f*PI/180.0f; + SetAngleZ(1, gunGoal); + } + else if ( m_type == OBJECT_MOBILErc ) // phazer? + { + if ( gunGoal > 45.0f*PI/180.0f ) gunGoal = 45.0f*PI/180.0f; + if ( gunGoal < -20.0f*PI/180.0f ) gunGoal = -20.0f*PI/180.0f; + SetAngleZ(2, gunGoal); + } + else + { + gunGoal = 0.0f; + } + + m_gunGoalV = gunGoal; +} + +void CObject::SetGunGoalH(float gunGoal) +{ + if ( m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEic ) // fireball? + { + if ( gunGoal > 40.0f*PI/180.0f ) gunGoal = 40.0f*PI/180.0f; + if ( gunGoal < -40.0f*PI/180.0f ) gunGoal = -40.0f*PI/180.0f; + SetAngleY(1, gunGoal); + } + else if ( m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEii ) // orgaball? + { + if ( gunGoal > 40.0f*PI/180.0f ) gunGoal = 40.0f*PI/180.0f; + if ( gunGoal < -40.0f*PI/180.0f ) gunGoal = -40.0f*PI/180.0f; + SetAngleY(1, gunGoal); + } + else if ( m_type == OBJECT_MOBILErc ) // phazer? + { + if ( gunGoal > 40.0f*PI/180.0f ) gunGoal = 40.0f*PI/180.0f; + if ( gunGoal < -40.0f*PI/180.0f ) gunGoal = -40.0f*PI/180.0f; + SetAngleY(2, gunGoal); + } + else + { + gunGoal = 0.0f; + } + + m_gunGoalH = gunGoal; +} + +float CObject::RetGunGoalV() +{ + return m_gunGoalV; +} + +float CObject::RetGunGoalH() +{ + return m_gunGoalH; +} + + + +// Shows the limits of the object. + +BOOL CObject::StartShowLimit() +{ + if ( m_showLimitRadius == 0.0f ) return FALSE; + + m_main->SetShowLimit(0, PARTILIMIT1, this, RetPosition(0), m_showLimitRadius); + m_bShowLimit = TRUE; + return TRUE; +} + +void CObject::StopShowLimit() +{ + m_bShowLimit = FALSE; +} + + + +// Indicates whether a program is under execution. + +BOOL CObject::IsProgram() +{ + if ( m_brain == 0 ) return FALSE; + return m_brain->IsProgram(); +} + + +// Creates or removes particles associated to the object. + +void CObject::CreateSelectParticule() +{ + D3DVECTOR pos, speed; + FPOINT dim; + int i; + + // Removes particles preceding. + for ( i=0 ; i<4 ; i++ ) + { + if ( m_partiSel[i] != -1 ) + { + m_particule->DeleteParticule(m_partiSel[i]); + m_partiSel[i] = -1; + } + } + + if ( m_bSelect || IsProgram() ) + { + // Creates particles lens for the headlights. + if ( m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEfs || + m_type == OBJECT_MOBILEts || + m_type == OBJECT_MOBILEws || + m_type == OBJECT_MOBILEis || + m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEtg || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILEdr ) // vehicle? + { + pos = D3DVECTOR(0.0f, 0.0f, 0.0f); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 0.0f; + dim.y = 0.0f; + m_partiSel[0] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f); + m_partiSel[1] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f); + m_partiSel[2] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f); + m_partiSel[3] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f); + UpdateSelectParticule(); + } + } +} + +// Updates the particles associated to the object. + +void CObject::UpdateSelectParticule() +{ + D3DVECTOR pos[4]; + FPOINT dim[4]; + float zoom[4]; + float angle; + int i; + + if ( !m_bSelect && !IsProgram() ) return; + + dim[0].x = 1.0f; + dim[1].x = 1.0f; + dim[2].x = 1.2f; + dim[3].x = 1.2f; + + // Lens front yellow. + if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) // large caterpillars? + { + pos[0] = D3DVECTOR(4.2f, 2.8f, 1.5f); + pos[1] = D3DVECTOR(4.2f, 2.8f, -1.5f); + dim[0].x = 1.5f; + dim[1].x = 1.5f; + } + else if ( m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEit ) // trainer ? + { + pos[0] = D3DVECTOR(4.2f, 2.5f, 1.2f); + pos[1] = D3DVECTOR(4.2f, 2.5f, -1.2f); + dim[0].x = 1.5f; + dim[1].x = 1.5f; + } + else if ( m_type == OBJECT_MOBILEsa ) // submarine? + { + pos[0] = D3DVECTOR(3.6f, 4.0f, 2.0f); + pos[1] = D3DVECTOR(3.6f, 4.0f, -2.0f); + } + else if ( m_type == OBJECT_MOBILEtg ) // target? + { + pos[0] = D3DVECTOR(3.4f, 6.5f, 2.0f); + pos[1] = D3DVECTOR(3.4f, 6.5f, -2.0f); + } + else if ( m_type == OBJECT_MOBILEdr ) // designer? + { + pos[0] = D3DVECTOR(4.9f, 3.5f, 2.5f); + pos[1] = D3DVECTOR(4.9f, 3.5f, -2.5f); + } + else + { + pos[0] = D3DVECTOR(4.2f, 2.5f, 1.5f); + pos[1] = D3DVECTOR(4.2f, 2.5f, -1.5f); + } + + // Red back lens + if ( m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEfs || + m_type == OBJECT_MOBILEft ) // flying? + { + pos[2] = D3DVECTOR(-4.0f, 3.1f, 4.5f); + pos[3] = D3DVECTOR(-4.0f, 3.1f, -4.5f); + dim[2].x = 0.6f; + dim[3].x = 0.6f; + } + if ( m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEws ) // wheels? + { + pos[2] = D3DVECTOR(-4.5f, 2.7f, 2.8f); + pos[3] = D3DVECTOR(-4.5f, 2.7f, -2.8f); + } + if ( m_type == OBJECT_MOBILEwt ) // wheels? + { + pos[2] = D3DVECTOR(-4.0f, 2.5f, 2.2f); + pos[3] = D3DVECTOR(-4.0f, 2.5f, -2.2f); + } + if ( m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEis || + m_type == OBJECT_MOBILEit ) // legs? + { + pos[2] = D3DVECTOR(-4.5f, 2.7f, 2.8f); + pos[3] = D3DVECTOR(-4.5f, 2.7f, -2.8f); + } + if ( m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEts || + m_type == OBJECT_MOBILEtt ) // caterpillars? + { + pos[2] = D3DVECTOR(-3.6f, 4.2f, 3.0f); + pos[3] = D3DVECTOR(-3.6f, 4.2f, -3.0f); + } + if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) // large caterpillars? + { + pos[2] = D3DVECTOR(-5.0f, 5.2f, 2.5f); + pos[3] = D3DVECTOR(-5.0f, 5.2f, -2.5f); + } + if ( m_type == OBJECT_MOBILEsa ) // submarine? + { + pos[2] = D3DVECTOR(-3.6f, 4.0f, 2.0f); + pos[3] = D3DVECTOR(-3.6f, 4.0f, -2.0f); + } + if ( m_type == OBJECT_MOBILEtg ) // target? + { + pos[2] = D3DVECTOR(-2.4f, 6.5f, 2.0f); + pos[3] = D3DVECTOR(-2.4f, 6.5f, -2.0f); + } + if ( m_type == OBJECT_MOBILEdr ) // designer? + { + pos[2] = D3DVECTOR(-5.3f, 2.7f, 1.8f); + pos[3] = D3DVECTOR(-5.3f, 2.7f, -1.8f); + } + + angle = RetAngleY(0)/PI; + + zoom[0] = 1.0f; + zoom[1] = 1.0f; + zoom[2] = 1.0f; + zoom[3] = 1.0f; + + if ( IsProgram() && // current program? + Mod(m_aTime, 0.7f) < 0.3f ) + { + zoom[0] = 0.0f; // blinks + zoom[1] = 0.0f; + zoom[2] = 0.0f; + zoom[3] = 0.0f; + } + + // Updates lens. + for ( i=0 ; i<4 ; i++ ) + { + pos[i] = Transform(m_objectPart[0].matWorld, pos[i]); + dim[i].y = dim[i].x; + m_particule->SetParam(m_partiSel[i], pos[i], dim[i], zoom[i], angle, 1.0f); + } +} + + +// Gives the pointer to the current script execution. + +void CObject::SetRunScript(CScript* script) +{ + m_runScript = script; +} + +CScript* CObject::RetRunScript() +{ + return m_runScript; +} + +// Returns the variables of "this" for CBOT. + +CBotVar* CObject::RetBotVar() +{ + return m_botVar; +} + +// Returns the physics associated to the object. + +CPhysics* CObject::RetPhysics() +{ + return m_physics; +} + +// Returns the brain associated to the object. + +CBrain* CObject::RetBrain() +{ + return m_brain; +} + +// Returns the movement associated to the object. + +CMotion* CObject::RetMotion() +{ + return m_motion; +} + +// Returns the controller associated to the object. + +CAuto* CObject::RetAuto() +{ + return m_auto; +} + +void CObject::SetAuto(CAuto* automat) +{ + m_auto = automat; +} + + + +// Management of the position in the file definition. + +void CObject::SetDefRank(int rank) +{ + m_defRank = rank; +} + +int CObject::RetDefRank() +{ + return m_defRank; +} + + +// Gives the object name for the tooltip. + +BOOL CObject::GetTooltipName(char* name) +{ + GetResource(RES_OBJECT, m_type, name); + return ( name[0] != 0 ); +} + + +// Adds the object previously selected in the list. + +void CObject::AddDeselList(CObject* pObj) +{ + int i; + + if ( m_totalDesectList >= OBJECTMAXDESELLIST ) + { + for ( i=0 ; iRetTraceDown(); +} + +void CObject::SetTraceDown(BOOL bDown) +{ + CMotionVehicle* mv; + if ( m_motion == 0 ) return; + mv = (CMotionVehicle*)m_motion; + mv->SetTraceDown(bDown); +} + +int CObject::RetTraceColor() +{ + CMotionVehicle* mv; + if ( m_motion == 0 ) return 0; + mv = (CMotionVehicle*)m_motion; + return mv->RetTraceColor(); +} + +void CObject::SetTraceColor(int color) +{ + CMotionVehicle* mv; + if ( m_motion == 0 ) return; + mv = (CMotionVehicle*)m_motion; + mv->SetTraceColor(color); +} + +float CObject::RetTraceWidth() +{ + CMotionVehicle* mv; + if ( m_motion == 0 ) return 0.0f; + mv = (CMotionVehicle*)m_motion; + return mv->RetTraceWidth(); +} + +void CObject::SetTraceWidth(float width) +{ + CMotionVehicle* mv; + if ( m_motion == 0 ) return; + mv = (CMotionVehicle*)m_motion; + mv->SetTraceWidth(width); +} + + diff --git a/src/object/object.h b/src/object/object.h new file mode 100644 index 0000000..af7a3e4 --- /dev/null +++ b/src/object/object.h @@ -0,0 +1,781 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// object.h + +#ifndef _OBJECT_H_ +#define _OBJECT_H_ + + +#include "d3dengine.h" +#include "camera.h" +#include "sound.h" + + +class CInstanceManager; +class CLight; +class CTerrain; +class CWater; +class CParticule; +class CPhysics; +class CBrain; +class CMotion; +class CAuto; +class CDisplayText; +class CRobotMain; +class CBotVar; +class CScript; + + + +// The father of all parts must always be the part number zero! + +#define OBJECTMAXPART 40 +#define MAXCRASHSPHERE 40 +#define OBJECTMAXDESELLIST 10 +#define OBJECTMAXINFO 10 +#define OBJECTMAXCMDLINE 20 + +enum ObjectType +{ + OBJECT_NULL = 0, // object destroyed + OBJECT_FIX = 1, // stationary scenery + OBJECT_PORTICO = 2, // gantry + OBJECT_BASE = 3, // great main base + OBJECT_DERRICK = 4, // derrick set + OBJECT_FACTORY = 5, // factory set + OBJECT_STATION = 6, // recharging station + OBJECT_CONVERT = 7, // converter station + OBJECT_REPAIR = 8, // reparation + OBJECT_TOWER = 9, // defense tower + OBJECT_NEST = 10, // nest + OBJECT_RESEARCH = 11, // research center + OBJECT_RADAR = 12, // radar + OBJECT_ENERGY = 13, // energy factory + OBJECT_LABO = 14, // analytical laboratory for insect + OBJECT_NUCLEAR = 15, // nuclear power plant + OBJECT_START = 16, // starting + OBJECT_END = 17, // finish + OBJECT_INFO = 18, // information terminal + OBJECT_PARA = 19, // lightning conductor + OBJECT_TARGET1 = 20, // gate target + OBJECT_TARGET2 = 21, // center target + OBJECT_SAFE = 22, // safe + OBJECT_HUSTON = 23, // control centre + OBJECT_DESTROYER = 24, // destroyer + OBJECT_FRET = 30, // transportable + OBJECT_STONE = 31, // stone + OBJECT_URANIUM = 32, // uranium + OBJECT_METAL = 33, // metal + OBJECT_POWER = 34, // normal battery + OBJECT_ATOMIC = 35, // atomic battery + OBJECT_BULLET = 36, // bullet + OBJECT_BBOX = 37, // black-box + OBJECT_TNT = 38, // box of TNT + OBJECT_SCRAP1 = 40, // metal waste + OBJECT_SCRAP2 = 41, // metal waste + OBJECT_SCRAP3 = 42, // metal waste + OBJECT_SCRAP4 = 43, // plastic waste + OBJECT_SCRAP5 = 44, // plastic waste + OBJECT_MARKPOWER = 50, // mark underground energy source + OBJECT_MARKSTONE = 51, // mark underground ore + OBJECT_MARKURANIUM = 52, // mark underground uranium + OBJECT_MARKKEYa = 53, // mark underground key + OBJECT_MARKKEYb = 54, // mark underground key + OBJECT_MARKKEYc = 55, // mark underground key + OBJECT_MARKKEYd = 56, // mark underground key + OBJECT_BOMB = 60, // bomb + OBJECT_WINFIRE = 61, // fireworks + OBJECT_SHOW = 62, // shows a place + OBJECT_BAG = 63, // survival bag + OBJECT_PLANT0 = 70, // plant 0 + OBJECT_PLANT1 = 71, // plant 1 + OBJECT_PLANT2 = 72, // plant 2 + OBJECT_PLANT3 = 73, // plant 3 + OBJECT_PLANT4 = 74, // plant 4 + OBJECT_PLANT5 = 75, // plant 5 + OBJECT_PLANT6 = 76, // plant 6 + OBJECT_PLANT7 = 77, // plant 7 + OBJECT_PLANT8 = 78, // plant 8 + OBJECT_PLANT9 = 79, // plant 9 + OBJECT_PLANT10 = 80, // plant 10 + OBJECT_PLANT11 = 81, // plant 11 + OBJECT_PLANT12 = 82, // plant 12 + OBJECT_PLANT13 = 83, // plant 13 + OBJECT_PLANT14 = 84, // plant 14 + OBJECT_PLANT15 = 85, // plant 15 + OBJECT_PLANT16 = 86, // plant 16 + OBJECT_PLANT17 = 87, // plant 17 + OBJECT_PLANT18 = 88, // plant 18 + OBJECT_PLANT19 = 89, // plant 19 + OBJECT_TREE0 = 90, // tree 0 + OBJECT_TREE1 = 91, // tree 1 + OBJECT_TREE2 = 92, // tree 2 + OBJECT_TREE3 = 93, // tree 3 + OBJECT_TREE4 = 94, // tree 4 + OBJECT_TREE5 = 95, // tree 5 + OBJECT_TREE6 = 96, // tree 6 + OBJECT_TREE7 = 97, // tree 7 + OBJECT_TREE8 = 98, // tree 8 + OBJECT_TREE9 = 99, // tree 9 + OBJECT_MOBILEwt = 100, // wheel-trainer + OBJECT_MOBILEtt = 101, // track-trainer + OBJECT_MOBILEft = 102, // fly-trainer + OBJECT_MOBILEit = 103, // insect-trainer + OBJECT_MOBILEwa = 110, // wheel-arm + OBJECT_MOBILEta = 111, // track-arm + OBJECT_MOBILEfa = 112, // fly-arm + OBJECT_MOBILEia = 113, // insect-arm + OBJECT_MOBILEwc = 120, // wheel-cannon + OBJECT_MOBILEtc = 121, // track-cannon + OBJECT_MOBILEfc = 122, // fly-cannon + OBJECT_MOBILEic = 123, // insect-cannon + OBJECT_MOBILEwi = 130, // wheel-insect-cannon + OBJECT_MOBILEti = 131, // track-insect-cannon + OBJECT_MOBILEfi = 132, // fly-insect-cannon + OBJECT_MOBILEii = 133, // insect-insect-cannon + OBJECT_MOBILEws = 140, // wheel-search + OBJECT_MOBILEts = 141, // track-search + OBJECT_MOBILEfs = 142, // fly-search + OBJECT_MOBILEis = 143, // insect-search + OBJECT_MOBILErt = 200, // roller-terraform + OBJECT_MOBILErc = 201, // roller-canon + OBJECT_MOBILErr = 202, // roller-recover + OBJECT_MOBILErs = 203, // roller-shield + OBJECT_MOBILEsa = 210, // submarine + OBJECT_MOBILEtg = 211, // training target + OBJECT_MOBILEdr = 212, // robot drawing + OBJECT_WAYPOINT = 250, // waypoint + OBJECT_FLAGb = 260, // blue flag + OBJECT_FLAGr = 261, // red flag + OBJECT_FLAGg = 262, // green flag + OBJECT_FLAGy = 263, // yellow flag + OBJECT_FLAGv = 264, // violet flag + OBJECT_KEYa = 270, // key a + OBJECT_KEYb = 271, // key b + OBJECT_KEYc = 272, // key c + OBJECT_KEYd = 273, // key d + OBJECT_HUMAN = 300, // human + OBJECT_TOTO = 301, // toto + OBJECT_TECH = 302, // technician + OBJECT_BARRIER0 = 400, // barrier + OBJECT_BARRIER1 = 401, // barrier + OBJECT_BARRIER2 = 402, // barrier + OBJECT_BARRIER3 = 403, // barrier + OBJECT_BARRIER4 = 404, // barrier + OBJECT_MOTHER = 500, // insect queen + OBJECT_EGG = 501, // egg + OBJECT_ANT = 502, // ant + OBJECT_SPIDER = 503, // spider + OBJECT_BEE = 504, // bee + OBJECT_WORM = 505, // worm + OBJECT_RUINmobilew1 = 600, // ruin 1 + OBJECT_RUINmobilew2 = 601, // ruin 1 + OBJECT_RUINmobilet1 = 602, // ruin 2 + OBJECT_RUINmobilet2 = 603, // ruin 2 + OBJECT_RUINmobiler1 = 604, // ruin 3 + OBJECT_RUINmobiler2 = 605, // ruin 3 + OBJECT_RUINfactory = 606, // ruin 4 + OBJECT_RUINdoor = 607, // ruin 5 + OBJECT_RUINsupport = 608, // ruin 6 + OBJECT_RUINradar = 609, // ruin 7 + OBJECT_RUINconvert = 610, // ruin 8 + OBJECT_RUINbase = 611, // ruin 9 + OBJECT_RUINhead = 612, // ruin 10 + OBJECT_TEEN0 = 620, // toy + OBJECT_TEEN1 = 621, // toy + OBJECT_TEEN2 = 622, // toy + OBJECT_TEEN3 = 623, // toy + OBJECT_TEEN4 = 624, // toy + OBJECT_TEEN5 = 625, // toy + OBJECT_TEEN6 = 626, // toy + OBJECT_TEEN7 = 627, // toy + OBJECT_TEEN8 = 628, // toy + OBJECT_TEEN9 = 629, // toy + OBJECT_TEEN10 = 630, // toy + OBJECT_TEEN11 = 631, // toy + OBJECT_TEEN12 = 632, // toy + OBJECT_TEEN13 = 633, // toy + OBJECT_TEEN14 = 634, // toy + OBJECT_TEEN15 = 635, // toy + OBJECT_TEEN16 = 636, // toy + OBJECT_TEEN17 = 637, // toy + OBJECT_TEEN18 = 638, // toy + OBJECT_TEEN19 = 639, // toy + OBJECT_TEEN20 = 640, // toy + OBJECT_TEEN21 = 641, // toy + OBJECT_TEEN22 = 642, // toy + OBJECT_TEEN23 = 643, // toy + OBJECT_TEEN24 = 644, // toy + OBJECT_TEEN25 = 645, // toy + OBJECT_TEEN26 = 646, // toy + OBJECT_TEEN27 = 647, // toy + OBJECT_TEEN28 = 648, // toy + OBJECT_TEEN29 = 649, // toy + OBJECT_TEEN30 = 650, // toy + OBJECT_TEEN31 = 651, // toy + OBJECT_TEEN32 = 652, // toy + OBJECT_TEEN33 = 653, // toy + OBJECT_TEEN34 = 654, // toy + OBJECT_TEEN35 = 655, // toy + OBJECT_TEEN36 = 656, // toy + OBJECT_TEEN37 = 657, // toy + OBJECT_TEEN38 = 658, // toy + OBJECT_TEEN39 = 659, // toy + OBJECT_TEEN40 = 660, // toy + OBJECT_TEEN41 = 661, // toy + OBJECT_TEEN42 = 662, // toy + OBJECT_TEEN43 = 663, // toy + OBJECT_TEEN44 = 664, // toy + OBJECT_TEEN45 = 665, // toy + OBJECT_TEEN46 = 666, // toy + OBJECT_TEEN47 = 667, // toy + OBJECT_TEEN48 = 668, // toy + OBJECT_TEEN49 = 669, // toy + OBJECT_QUARTZ0 = 700, // crystal 0 + OBJECT_QUARTZ1 = 701, // crystal 1 + OBJECT_QUARTZ2 = 702, // crystal 2 + OBJECT_QUARTZ3 = 703, // crystal 3 + OBJECT_QUARTZ4 = 704, // crystal 4 + OBJECT_QUARTZ5 = 705, // crystal 5 + OBJECT_QUARTZ6 = 706, // crystal 6 + OBJECT_QUARTZ7 = 707, // crystal 7 + OBJECT_QUARTZ8 = 708, // crystal 8 + OBJECT_QUARTZ9 = 709, // crystal 9 + OBJECT_ROOT0 = 710, // root 0 + OBJECT_ROOT1 = 711, // root 1 + OBJECT_ROOT2 = 712, // root 2 + OBJECT_ROOT3 = 713, // root 3 + OBJECT_ROOT4 = 714, // root 4 + OBJECT_ROOT5 = 715, // root 5 + OBJECT_ROOT6 = 716, // root 6 + OBJECT_ROOT7 = 717, // root 7 + OBJECT_ROOT8 = 718, // root 8 + OBJECT_ROOT9 = 719, // root 9 + OBJECT_SEAWEED0 = 720, // seaweed 0 + OBJECT_SEAWEED1 = 721, // seaweed 1 + OBJECT_SEAWEED2 = 722, // seaweed 2 + OBJECT_SEAWEED3 = 723, // seaweed 3 + OBJECT_SEAWEED4 = 724, // seaweed 4 + OBJECT_SEAWEED5 = 725, // seaweed 5 + OBJECT_SEAWEED6 = 726, // seaweed 6 + OBJECT_SEAWEED7 = 727, // seaweed 7 + OBJECT_SEAWEED8 = 728, // seaweed 8 + OBJECT_SEAWEED9 = 729, // seaweed 9 + OBJECT_MUSHROOM0 = 730, // mushroom 0 + OBJECT_MUSHROOM1 = 731, // mushroom 1 + OBJECT_MUSHROOM2 = 732, // mushroom 2 + OBJECT_MUSHROOM3 = 733, // mushroom 3 + OBJECT_MUSHROOM4 = 734, // mushroom 4 + OBJECT_MUSHROOM5 = 735, // mushroom 5 + OBJECT_MUSHROOM6 = 736, // mushroom 6 + OBJECT_MUSHROOM7 = 737, // mushroom 7 + OBJECT_MUSHROOM8 = 738, // mushroom 8 + OBJECT_MUSHROOM9 = 739, // mushroom 9 + OBJECT_APOLLO1 = 900, // apollo lem + OBJECT_APOLLO2 = 901, // apollo jeep + OBJECT_APOLLO3 = 902, // apollo flag + OBJECT_APOLLO4 = 903, // apollo module + OBJECT_APOLLO5 = 904, // apollo antenna + OBJECT_HOME1 = 910, // home 1 + OBJECT_MAX = 1000, +}; + +enum ObjectMaterial +{ + OM_METAL = 0, // metal + OM_PLASTIC = 1, // plastic + OM_HUMAN = 2, // cosmonaut + OM_ANIMAL = 3, // insect + OM_VEGETAL = 4, // plant + OM_MINERAL = 5, // stone +}; + +typedef struct +{ + char bUsed; + int object; // number of the object in CD3DEngine + int parentPart; // number of father part + int masterParti; // master canal of the particle + D3DVECTOR position; + D3DVECTOR angle; + D3DVECTOR zoom; + char bTranslate; + char bRotate; + char bZoom; + D3DMATRIX matTranslate; + D3DMATRIX matRotate; + D3DMATRIX matTransform; + D3DMATRIX matWorld; +} +ObjectPart; + +typedef struct +{ + float wheelFront; // position X of the front wheels + float wheelBack; // position X of the back wheels + float wheelLeft; // position Z of the left wheels + float wheelRight; // position Z of the right wheels + float height; // normal height on top of ground + D3DVECTOR posPower; // position of the battery +} +Character; + +typedef struct +{ + char name[20]; // name of the information + float value; // value of the information +} +Info; + +enum ExploType +{ + EXPLO_BOUM = 1, + EXPLO_BURN = 2, + EXPLO_WATER = 3, +}; + +enum ResetCap +{ + RESET_NONE = 0, + RESET_MOVE = 1, + RESET_DELETE = 2, +}; + +enum RadarFilter +{ + FILTER_NONE = 0, + FILTER_ONLYLANDING = 1, + FILTER_ONLYFLYING = 2, +}; + + + + +class CObject +{ +public: + CObject(CInstanceManager* iMan); + ~CObject(); + + void DeleteObject(BOOL bAll=FALSE); + void Simplify(); + BOOL ExploObject(ExploType type, float force, float decay=1.0f); + + BOOL EventProcess(const Event &event); + void UpdateMapping(); + + int CreatePart(); + void DeletePart(int part); + void SetObjectRank(int part, int objRank); + int RetObjectRank(int part); + void SetObjectParent(int part, int parent); + void SetType(ObjectType type); + ObjectType RetType(); + char* RetName(); + void SetOption(int option); + int RetOption(); + + void SetID(int id); + int RetID(); + + BOOL Write(char *line); + BOOL Read(char *line); + + void SetDrawWorld(BOOL bDraw); + void SetDrawFront(BOOL bDraw); + + BOOL CreateVehicle(D3DVECTOR pos, float angle, ObjectType type, float power, BOOL bTrainer, BOOL bToy); + BOOL CreateInsect(D3DVECTOR pos, float angle, ObjectType type); + BOOL CreateBuilding(D3DVECTOR pos, float angle, float height, ObjectType type, float power=1.0f); + BOOL CreateResource(D3DVECTOR pos, float angle, ObjectType type, float power=1.0f); + BOOL CreateFlag(D3DVECTOR pos, float angle, ObjectType type); + BOOL CreateBarrier(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreatePlant(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateMushroom(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateTeen(D3DVECTOR pos, float angle, float zoom, float height, ObjectType type); + BOOL CreateQuartz(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateRoot(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateHome(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateRuin(D3DVECTOR pos, float angle, float height, ObjectType type); + BOOL CreateApollo(D3DVECTOR pos, float angle, ObjectType type); + + BOOL ReadProgram(int rank, char* filename); + BOOL WriteProgram(int rank, char* filename); + BOOL RunProgram(int rank); + + int RetShadowLight(); + int RetEffectLight(); + + void FlushCrashShere(); + int CreateCrashSphere(D3DVECTOR pos, float radius, Sound sound, float hardness=0.45f); + int RetCrashSphereTotal(); + BOOL GetCrashSphere(int rank, D3DVECTOR &pos, float &radius); + float RetCrashSphereHardness(int rank); + Sound RetCrashSphereSound(int rank); + void DeleteCrashSphere(int rank); + void SetGlobalSphere(D3DVECTOR pos, float radius); + void GetGlobalSphere(D3DVECTOR &pos, float &radius); + void SetJotlerSphere(D3DVECTOR pos, float radius); + void GetJotlerSphere(D3DVECTOR &pos, float &radius); + void SetShieldRadius(float radius); + float RetShieldRadius(); + + void SetFloorHeight(float height); + void FloorAdjust(); + + void SetLinVibration(D3DVECTOR dir); + D3DVECTOR RetLinVibration(); + void SetCirVibration(D3DVECTOR dir); + D3DVECTOR RetCirVibration(); + void SetInclinaison(D3DVECTOR dir); + D3DVECTOR RetInclinaison(); + + void SetPosition(int part, const D3DVECTOR &pos); + D3DVECTOR RetPosition(int part); + void SetAngle(int part, const D3DVECTOR &angle); + D3DVECTOR RetAngle(int part); + void SetAngleY(int part, float angle); + void SetAngleX(int part, float angle); + void SetAngleZ(int part, float angle); + float RetAngleY(int part); + float RetAngleX(int part); + float RetAngleZ(int part); + void SetZoom(int part, float zoom); + void SetZoom(int part, D3DVECTOR zoom); + D3DVECTOR RetZoom(int part); + void SetZoomX(int part, float zoom); + float RetZoomX(int part); + void SetZoomY(int part, float zoom); + float RetZoomY(int part); + void SetZoomZ(int part, float zoom); + float RetZoomZ(int part); + + float RetWaterLevel(); + + void SetTrainer(BOOL bEnable); + BOOL RetTrainer(); + + void SetToy(BOOL bEnable); + BOOL RetToy(); + + void SetManual(BOOL bManual); + BOOL RetManual(); + + void SetResetCap(ResetCap cap); + ResetCap RetResetCap(); + void SetResetBusy(BOOL bBusy); + BOOL RetResetBusy(); + void SetResetPosition(const D3DVECTOR &pos); + D3DVECTOR RetResetPosition(); + void SetResetAngle(const D3DVECTOR &angle); + D3DVECTOR RetResetAngle(); + void SetResetRun(int run); + int RetResetRun(); + + void SetMasterParticule(int part, int parti); + int RetMasterParticule(int part); + + void SetPower(CObject* power); + CObject* RetPower(); + void SetFret(CObject* fret); + CObject* RetFret(); + void SetTruck(CObject* truck); + CObject* RetTruck(); + void SetTruckPart(int part); + int RetTruckPart(); + + void InfoFlush(); + void DeleteInfo(int rank); + void SetInfo(int rank, Info info); + Info RetInfo(int rank); + int RetInfoTotal(); + void SetInfoReturn(float value); + float RetInfoReturn(); + void SetInfoUpdate(BOOL bUpdate); + BOOL RetInfoUpdate(); + + BOOL SetCmdLine(int rank, float value); + float RetCmdLine(int rank); + + D3DMATRIX* RetRotateMatrix(int part); + D3DMATRIX* RetTranslateMatrix(int part); + D3DMATRIX* RetTransformMatrix(int part); + D3DMATRIX* RetWorldMatrix(int part); + + void SetViewFromHere(D3DVECTOR &eye, float &dirH, float &dirV, D3DVECTOR &lookat, D3DVECTOR &upVec, CameraType type); + + void SetCharacter(Character* character); + void GetCharacter(Character* character); + Character* RetCharacter(); + + float RetAbsTime(); + + void SetEnergy(float level); + float RetEnergy(); + + void SetCapacity(float capacity); + float RetCapacity(); + + void SetShield(float level); + float RetShield(); + + void SetRange(float delay); + float RetRange(); + + void SetTransparency(float value); + float RetTransparency(); + + ObjectMaterial RetMaterial(); + + void SetGadget(BOOL bMode); + BOOL RetGadget(); + + void SetFixed(BOOL bFixed); + BOOL RetFixed(); + + void SetClip(BOOL bClip); + BOOL RetClip(); + + BOOL JostleObject(float force); + + void StartDetectEffect(CObject *target, BOOL bFound); + + void SetVirusMode(BOOL bEnable); + BOOL RetVirusMode(); + float RetVirusTime(); + + void SetCameraType(CameraType type); + CameraType RetCameraType(); + void SetCameraDist(float dist); + float RetCameraDist(); + void SetCameraLock(BOOL bLock); + BOOL RetCameraLock(); + + void SetHilite(BOOL bMode); + BOOL RetHilite(); + + void SetSelect(BOOL bMode, BOOL bDisplayError=TRUE); + BOOL RetSelect(BOOL bReal=FALSE); + + void SetSelectable(BOOL bMode); + BOOL RetSelectable(); + + void SetActivity(BOOL bMode); + BOOL RetActivity(); + + void SetVisible(BOOL bVisible); + BOOL RetVisible(); + + void SetEnable(BOOL bEnable); + BOOL RetEnable(); + + void SetCheckToken(BOOL bMode); + BOOL RetCheckToken(); + + void SetProxyActivate(BOOL bActivate); + BOOL RetProxyActivate(); + void SetProxyDistance(float distance); + float RetProxyDistance(); + + void SetMagnifyDamage(float factor); + float RetMagnifyDamage(); + + void SetParam(float value); + float RetParam(); + + void SetExplo(BOOL bExplo); + BOOL RetExplo(); + void SetLock(BOOL bLock); + BOOL RetLock(); + void SetCargo(BOOL bCargo); + BOOL RetCargo(); + void SetBurn(BOOL bBurn); + BOOL RetBurn(); + void SetDead(BOOL bDead); + BOOL RetDead(); + BOOL RetRuin(); + BOOL RetActif(); + + void SetGunGoalV(float gunGoal); + void SetGunGoalH(float gunGoal); + float RetGunGoalV(); + float RetGunGoalH(); + + BOOL StartShowLimit(); + void StopShowLimit(); + + BOOL IsProgram(); + void CreateSelectParticule(); + + void SetRunScript(CScript* script); + CScript* RetRunScript(); + CBotVar* RetBotVar(); + CPhysics* RetPhysics(); + CBrain* RetBrain(); + CMotion* RetMotion(); + CAuto* RetAuto(); + void SetAuto(CAuto* automat); + + void SetDefRank(int rank); + int RetDefRank(); + + BOOL GetTooltipName(char* name); + + void AddDeselList(CObject* pObj); + CObject* SubDeselList(); + void DeleteDeselList(CObject* pObj); + + BOOL CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM); + BOOL CreateShadowLight(float height, D3DCOLORVALUE color); + BOOL CreateEffectLight(float height, D3DCOLORVALUE color); + + void FlatParent(); + + BOOL RetTraceDown(); + void SetTraceDown(BOOL bDown); + int RetTraceColor(); + void SetTraceColor(int color); + float RetTraceWidth(); + void SetTraceWidth(float width); + +protected: + BOOL EventFrame(const Event &event); + void VirusFrame(float rTime); + void PartiFrame(float rTime); + void CreateOtherObject(ObjectType type); + void InitPart(int part); + void UpdateTotalPart(); + int SearchDescendant(int parent, int n); + void UpdateEnergyMapping(); + BOOL UpdateTransformObject(int part, BOOL bForceUpdate); + BOOL UpdateTransformObject(); + void UpdateSelectParticule(); + +protected: + CInstanceManager* m_iMan; + CD3DEngine* m_engine; + CLight* m_light; + CTerrain* m_terrain; + CWater* m_water; + CCamera* m_camera; + CParticule* m_particule; + CPhysics* m_physics; + CBrain* m_brain; + CMotion* m_motion; + CAuto* m_auto; + CDisplayText* m_displayText; + CRobotMain* m_main; + CSound* m_sound; + CBotVar* m_botVar; + CScript* m_runScript; + + ObjectType m_type; // OBJECT_* + int m_id; // unique identifier + char m_name[50]; // name of the object + Character m_character; // characteristic + int m_option; // option + int m_partiReactor; // number of the particle of the reactor + int m_shadowLight; // number of light from the shadows + float m_shadowHeight; // height of light from the shadows + int m_effectLight; // number of light effects + float m_effectHeight; // height of light effects + D3DVECTOR m_linVibration; // linear vibration + D3DVECTOR m_cirVibration; // circular vibration + D3DVECTOR m_inclinaison; // tilt + CObject* m_power; // battery used by the vehicle + CObject* m_fret; // object transported + CObject* m_truck; // object with the latter + int m_truckLink; // part + float m_energy; // energy contained (if battery) + float m_lastEnergy; + float m_capacity; // capacity (if battery) + float m_shield; // shield + float m_range; // flight range + float m_transparency; // transparency (0..1) + int m_material; // matter(0..n) + float m_aTime; + float m_shotTime; // time since last shot + BOOL m_bVirusMode; // virus activated/triggered + float m_virusTime; // lifetime of the virus + float m_lastVirusParticule; + float m_lastParticule; + BOOL m_bHilite; + BOOL m_bSelect; // object selected + BOOL m_bSelectable; // selectable object + BOOL m_bCheckToken; // object with audited tokens + BOOL m_bVisible; // object active but undetectable + BOOL m_bEnable; // dead object + BOOL m_bProxyActivate; // active object so close + BOOL m_bGadget; // object nonessential + BOOL m_bLock; + BOOL m_bExplo; + BOOL m_bCargo; + BOOL m_bBurn; + BOOL m_bDead; + BOOL m_bFlat; + BOOL m_bTrainer; // drive vehicle (without remote) + BOOL m_bToy; // toy key + BOOL m_bManual; // manual control (Scribbler) + BOOL m_bFixed; + BOOL m_bClip; + BOOL m_bShowLimit; + float m_showLimitRadius; + float m_gunGoalV; + float m_gunGoalH; + CameraType m_cameraType; + float m_cameraDist; + BOOL m_bCameraLock; + int m_defRank; + float m_magnifyDamage; + float m_proxyDistance; + float m_param; + + int m_crashSphereUsed; // number of spheres used + D3DVECTOR m_crashSpherePos[MAXCRASHSPHERE]; + float m_crashSphereRadius[MAXCRASHSPHERE]; + float m_crashSphereHardness[MAXCRASHSPHERE]; + Sound m_crashSphereSound[MAXCRASHSPHERE]; + D3DVECTOR m_globalSpherePos; + float m_globalSphereRadius; + D3DVECTOR m_jotlerSpherePos; + float m_jotlerSphereRadius; + float m_shieldRadius; + + int m_totalPart; + ObjectPart m_objectPart[OBJECTMAXPART]; + + int m_totalDesectList; + CObject* m_objectDeselectList[OBJECTMAXDESELLIST]; + + int m_partiSel[4]; + + ResetCap m_resetCap; + BOOL m_bResetBusy; + D3DVECTOR m_resetPosition; + D3DVECTOR m_resetAngle; + int m_resetRun; + + int m_infoTotal; + Info m_info[OBJECTMAXINFO]; + float m_infoReturn; + BOOL m_bInfoUpdate; + + float m_cmdLine[OBJECTMAXCMDLINE]; +}; + + +#endif //_OBJECT_H_ diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp new file mode 100644 index 0000000..a6d92e5 --- /dev/null +++ b/src/object/robotmain.cpp @@ -0,0 +1,7031 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// robotmain.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "CBot/CBotDll.h" +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "language.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "profile.h" +#include "iman.h" +#include "restext.h" +#include "math3d.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "cloud.h" +#include "blitz.h" +#include "planet.h" +#include "object.h" +#include "motion.h" +#include "motiontoto.h" +#include "motionhuman.h" +#include "physics.h" +#include "brain.h" +#include "pyro.h" +#include "modfile.h" +#include "model.h" +#include "camera.h" +#include "task.h" +#include "taskmanip.h" +#include "taskbuild.h" +#include "auto.h" +#include "autobase.h" +#include "displayinfo.h" +#include "interface.h" +#include "shortcut.h" +#include "map.h" +#include "label.h" +#include "button.h" +#include "slider.h" +#include "window.h" +#include "edit.h" +#include "displaytext.h" +#include "text.h" +#include "sound.h" +#include "cbottoken.h" +#include "cmdtoken.h" +#include "mainmovie.h" +#include "maindialog.h" +#include "mainshort.h" +#include "mainmap.h" +#include "script.h" +#include "robotmain.h" + + + +#define CBOT_STACK TRUE // saves the stack of programs CBOT +#define UNIT 4.0f + + + +// Global variables. + +long g_id; // unique identifier +long g_build; // constructible buildings +long g_researchDone; // research done +long g_researchEnable; // research available +float g_unit; // conversion factor + + + +#include "ClassFILE.cpp" + + + +// Compilation of class "point". + +CBotTypResult cPoint(CBotVar* pThis, CBotVar* &var) +{ + if ( !pThis->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadNum); + + if ( var == NULL ) return CBotTypResult(0); // ok if no parameter + + // First parameter (x): + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + // Second parameter (y): + if ( var == NULL ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + // Third parameter (z): + if ( var == NULL ) // only 2 parameters? + { + return CBotTypResult(0); // this function returns void + } + + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != NULL ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(0); // this function returns void +} + +//Execution of the class "point". + +BOOL rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception) +{ + CBotVar *pX, *pY, *pZ; + + if ( var == NULL ) return TRUE; // constructor with no parameters is ok + + if ( var->GivType() > CBotTypDouble ) + { + Exception = CBotErrBadNum; return FALSE; + } + + pX = pThis->GivItem("x"); + if ( pX == NULL ) + { + Exception = CBotErrUndefItem; return FALSE; + } + pX->SetValFloat( var->GivValFloat() ); + var = var->GivNext(); + + if ( var == NULL ) + { + Exception = CBotErrLowParam; return FALSE; + } + + if ( var->GivType() > CBotTypDouble ) + { + Exception = CBotErrBadNum; return FALSE; + } + + pY = pThis->GivItem("y"); + if ( pY == NULL ) + { + Exception = CBotErrUndefItem; return FALSE; + } + pY->SetValFloat( var->GivValFloat() ); + var = var->GivNext(); + + if ( var == NULL ) + { + return TRUE; // ok with only two parameters + } + + pZ = pThis->GivItem("z"); + if ( pZ == NULL ) + { + Exception = CBotErrUndefItem; return FALSE; + } + pZ->SetValFloat( var->GivValFloat() ); + var = var->GivNext(); + + if ( var != NULL ) + { + Exception = CBotErrOverParam; return FALSE; + } + + return TRUE; // no interruption +} + + + + +// Constructor of robot application. + +CRobotMain::CRobotMain(CInstanceManager* iMan) +{ + ObjectType type; + float fValue; + int iValue, i; + char* token; + + m_iMan = iMan; + m_iMan->AddInstance(CLASS_MAIN, this); + + m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT); + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD); + m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ); + m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + + m_interface = new CInterface(m_iMan); + m_terrain = new CTerrain(m_iMan); + m_model = new CModel(m_iMan); + m_camera = new CCamera(m_iMan); + m_displayText = new CDisplayText(m_iMan); + m_movie = new CMainMovie(m_iMan); + m_dialog = new CMainDialog(m_iMan); + m_short = new CMainShort(m_iMan); + m_map = new CMainMap(m_iMan); + m_displayInfo = 0; + + m_engine->SetTerrain(m_terrain); + m_filesDir = m_dialog->RetFilesDir(); + + m_time = 0.0f; + m_gameTime = 0.0f; + m_checkEndTime = 0.0f; + + m_phase = PHASE_NAME; + m_cameraRank = -1; + m_visitLast = EVENT_NULL; + m_visitObject = 0; + m_visitArrow = 0; + m_audioTrack = 0; + m_bAudioRepeat = TRUE; + m_delayWriteMessage = 0; + m_selectObject = 0; + m_infoUsed = 0; + + m_bBeginSatCom = FALSE; + m_bMovieLock = FALSE; + m_bSatComLock = FALSE; + m_bEditLock = FALSE; + m_bEditFull = FALSE; + m_bPause = FALSE; + m_bHilite = FALSE; + m_bFreePhoto = FALSE; + m_bShowPos = FALSE; + m_bSelectInsect = FALSE; + m_bShowSoluce = FALSE; + m_bShowAll = FALSE; + m_bCheatRadar = FALSE; + m_bFixScene = FALSE; + m_bTrainerPilot = FALSE; + m_bSuspend = FALSE; + m_bFriendAim = FALSE; + m_bResetCreate = FALSE; + m_bShortCut = TRUE; + + m_engine->SetMovieLock(m_bMovieLock); + + m_movie->Flush(); + m_movieInfoIndex = -1; + + m_tooltipPos = FPOINT(0.0f, 0.0f); + m_tooltipName[0] = 0; + m_tooltipTime = 0.0f; + + m_endingWinRank = 0; + m_endingLostRank = 0; + m_bWinTerminate = FALSE; + + FlushDisplayInfo(); + + m_fontSize = 9.0f; + m_windowPos = FPOINT(0.15f, 0.17f); + m_windowDim = FPOINT(0.70f, 0.66f); + + if ( GetProfileFloat("Edit", "FontSize", fValue) ) m_fontSize = fValue; + if ( GetProfileFloat("Edit", "WindowPos.x", fValue) ) m_windowPos.x = fValue; + if ( GetProfileFloat("Edit", "WindowPos.y", fValue) ) m_windowPos.y = fValue; + if ( GetProfileFloat("Edit", "WindowDim.x", fValue) ) m_windowDim.x = fValue; + if ( GetProfileFloat("Edit", "WindowDim.y", fValue) ) m_windowDim.y = fValue; + + m_IOPublic = FALSE; + m_IODim = FPOINT(320.0f/640.0f, (121.0f+18.0f*8)/480.0f); + m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle + m_IOPos.y = (1.0f-m_IODim.y)/2.0f; + + if ( GetProfileInt ("Edit", "IOPublic", iValue) ) m_IOPublic = iValue; + if ( GetProfileFloat("Edit", "IOPos.x", fValue) ) m_IOPos.x = fValue; + if ( GetProfileFloat("Edit", "IOPos.y", fValue) ) m_IOPos.y = fValue; + if ( GetProfileFloat("Edit", "IODim.x", fValue) ) m_IODim.x = fValue; + if ( GetProfileFloat("Edit", "IODim.y", fValue) ) m_IODim.y = fValue; + + m_short->FlushShortcuts(); + InitEye(); + + m_engine->SetTracePrecision(1.0f); + + m_cameraPan = 0.0f; + m_cameraZoom = 0.0f; + + g_id = 0; + g_build = 0; + g_researchDone = 0; // no research done + g_researchEnable = 0; + g_unit = 4.0f; + + m_gamerName[0] = 0; + GetProfileString("Gamer", "LastName", m_gamerName, 100); + SetGlobalGamerName(m_gamerName); + ReadFreeParam(); + m_dialog->SetupRecall(); + + for ( i=0 ; iAddItem("x", CBotTypFloat); + bc->AddItem("y", CBotTypFloat); + bc->AddItem("z", CBotTypFloat); + bc->AddFunction("point", rPoint, cPoint); + + // Adds the class Object. + bc = new CBotClass("object", NULL); + bc->AddItem("category", CBotTypResult(CBotTypInt), PR_READ); + bc->AddItem("position", CBotTypResult(CBotTypClass, "point"), PR_READ); + bc->AddItem("orientation", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("pitch", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("roll", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("energyLevel", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("shieldLevel", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("temperature", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("altitude", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("lifeTime", CBotTypResult(CBotTypFloat), PR_READ); + bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ); + bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ); + bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ); + + // Initializes the class FILE. + InitClassFILE(); + + CScript::InitFonctions(); +} + +// Destructor of robot application. + +CRobotMain::~CRobotMain() +{ + delete m_movie; + delete m_dialog; + delete m_short; + delete m_map; + delete m_terrain; + delete m_model; +} + + +// Creates the file colobot.ini at the first time. + +void CRobotMain::CreateIni() +{ + int iValue; + + // colobot.ini don't exist? + if ( !GetProfileInt("Setup", "TotoMode", iValue) ) + { + m_dialog->SetupMemorize(); + } +} + + +// Changes phase. + +void CRobotMain::ChangePhase(Phase phase) +{ + CEdit* pe; + CButton* pb; + D3DCOLORVALUE color; + FPOINT pos, dim, ddim; + float ox, oy, sx, sy; + char* read; + int rank, numTry; + BOOL bLoading; + + if ( m_phase == PHASE_SIMUL ) // ends a simulation? + { + SaveAllScript(); + m_sound->StopMusic(); + m_camera->SetObject(0); + +#if _SCHOOL + if ( TRUE ) +#else + if ( m_gameTime > 10.0f ) // did you play at least 10 seconds? +#endif + { + rank = m_dialog->RetSceneRank(); + numTry = m_dialog->RetGamerInfoTry(rank); + m_dialog->SetGamerInfoTry(rank, numTry+1); + m_dialog->WriteGamerInfo(); + } + } + + if ( phase == PHASE_WIN ) // wins a simulation? + { + rank = m_dialog->RetSceneRank(); + m_dialog->SetGamerInfoPassed(rank, TRUE); + m_dialog->NextMission(); // passes to the next mission + m_dialog->WriteGamerInfo(); + } + + DeleteAllObjects(); // removes all the current 3D Scene + + m_phase = phase; + m_winDelay = 0.0f; + m_lostDelay = 0.0f; + m_bBeginSatCom = FALSE; + m_bMovieLock = FALSE; + m_bSatComLock = FALSE; + m_bEditLock = FALSE; + m_bFreePhoto = FALSE; + m_bResetCreate = FALSE; + + m_engine->SetMovieLock(m_bMovieLock); + ChangePause(FALSE); + FlushDisplayInfo(); + m_engine->SetRankView(0); + m_engine->FlushObject(); + color.r = color.g = color.b = color.a = 0.0f; + m_engine->SetWaterAddColor(color); + m_engine->SetBackground(""); + m_engine->SetBackForce(FALSE); + m_engine->SetFrontsizeName(""); + m_engine->SetOverColor(); + m_engine->GroundMarkDelete(0); + SetSpeed(1.0f); + m_terrain->SetWind(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_terrain->FlushBuildingLevel(); + m_terrain->FlushFlyingLimit(); + m_light->FlushLight(); + m_particule->FlushParticule(); + m_water->Flush(); + m_cloud->Flush(); + m_blitz->Flush(); + m_planet->Flush(); + m_iMan->Flush(CLASS_OBJECT); + m_iMan->Flush(CLASS_PHYSICS); + m_iMan->Flush(CLASS_BRAIN); + m_iMan->Flush(CLASS_PYRO); + m_model->StopUserAction(); + m_interface->Flush(); + ClearInterface(); + FlushNewScriptName(); + m_sound->SetListener(D3DVECTOR(0.0f, 0.0f, 0.0f), D3DVECTOR(0.0f, 0.0f, 1.0f)); + m_camera->SetType(CAMERA_DIALOG); + m_movie->Flush(); + m_movieInfoIndex = -1; + m_cameraPan = 0.0f; + m_cameraZoom = 0.0f; + m_bShortCut = TRUE; + + // Creates and hide the command console. + dim.x = 200.0f/640.0f; + dim.y = 18.0f/480.0f; + pos.x = 50.0f/640.0f; + pos.y = 452.0f/480.0f; + pe = m_interface->CreateEdit(pos, dim, 0, EVENT_CMD); + if ( pe == 0 ) return; + pe->ClearState(STATE_VISIBLE); + m_bCmdEdit = FALSE; // hidden for now + + // Creates the speedometer. +#if _TEEN + dim.x = 30.0f/640.0f; + dim.y = 20.0f/480.0f; + pos.x = 4.0f/640.0f; + pos.y = 454.0f/480.0f; +#else + dim.x = 30.0f/640.0f; + dim.y = 20.0f/480.0f; + pos.x = 4.0f/640.0f; + pos.y = 426.0f/480.0f; +#endif + pb = m_interface->CreateButton(pos, dim, 0, EVENT_SPEED); + if ( pb == 0 ) return; + pb->SetState(STATE_SIMPLY); + pb->ClearState(STATE_VISIBLE); + + m_dialog->ChangePhase(m_phase); + + dim.x = 32.0f/640.0f; + dim.y = 32.0f/480.0f; + ox = 3.0f/640.0f; + oy = 3.0f/480.0f; + sx = (32.0f+2.0f)/640.0f; + sy = (32.0f+2.0f)/480.0f; + + if ( m_phase != PHASE_PERSO ) + { + m_engine->SetDrawWorld(TRUE); + m_engine->SetDrawFront(FALSE); + m_bFixScene = FALSE; + } + + if ( m_phase == PHASE_INIT ) + { +#if _NEWLOOK + m_engine->FreeTexture("generna.tga"); + m_engine->FreeTexture("genernb.tga"); + m_engine->FreeTexture("genernc.tga"); + m_engine->FreeTexture("genernd.tga"); +#else +#if _FRENCH +#if _DEMO + m_engine->FreeTexture("genedfa.tga"); + m_engine->FreeTexture("genedfb.tga"); + m_engine->FreeTexture("genedfc.tga"); + m_engine->FreeTexture("genedfd.tga"); +#else + m_engine->FreeTexture("generfa.tga"); + m_engine->FreeTexture("generfb.tga"); + m_engine->FreeTexture("generfc.tga"); + m_engine->FreeTexture("generfd.tga"); +#endif +#endif +#if _ENGLISH +#if _DEMO + m_engine->FreeTexture("genedea.tga"); + m_engine->FreeTexture("genedeb.tga"); + m_engine->FreeTexture("genedec.tga"); + m_engine->FreeTexture("geneded.tga"); +#else + m_engine->FreeTexture("generea.tga"); + m_engine->FreeTexture("genereb.tga"); + m_engine->FreeTexture("generec.tga"); + m_engine->FreeTexture("genered.tga"); +#endif +#endif +#if _GERMAN +#if _DEMO + m_engine->FreeTexture("genedda.tga"); + m_engine->FreeTexture("geneddb.tga"); + m_engine->FreeTexture("geneddc.tga"); + m_engine->FreeTexture("geneddd.tga"); +#else + m_engine->FreeTexture("generea.tga"); + m_engine->FreeTexture("genereb.tga"); + m_engine->FreeTexture("generec.tga"); + m_engine->FreeTexture("genered.tga"); +#endif +#endif +#if _WG +#if _DEMO + m_engine->FreeTexture("genedda.tga"); + m_engine->FreeTexture("geneddb.tga"); + m_engine->FreeTexture("geneddc.tga"); + m_engine->FreeTexture("geneddd.tga"); +#else + m_engine->FreeTexture("generda.tga"); + m_engine->FreeTexture("generdb.tga"); + m_engine->FreeTexture("generdc.tga"); + m_engine->FreeTexture("generdd.tga"); +#endif +#endif +#if _POLISH +#if _DEMO + m_engine->FreeTexture("genedpa.tga"); + m_engine->FreeTexture("genedpb.tga"); + m_engine->FreeTexture("genedpc.tga"); + m_engine->FreeTexture("genedpd.tga"); +#else + m_engine->FreeTexture("generpa.tga"); + m_engine->FreeTexture("generpb.tga"); + m_engine->FreeTexture("generpc.tga"); + m_engine->FreeTexture("generpd.tga"); +#endif +#endif +#endif + } + + if ( m_phase == PHASE_SIMUL ) + { + m_engine->FreeTexture("inter01a.tga"); + m_engine->FreeTexture("inter01b.tga"); + m_engine->FreeTexture("inter01c.tga"); + m_engine->FreeTexture("inter01d.tga"); + + read = m_dialog->RetSceneRead(); + bLoading = (read[0] != 0); + + m_map->CreateMap(); + CreateScene(m_dialog->RetSceneSoluce(), FALSE, FALSE); // interactive scene + if ( m_bMapImage ) + { + m_map->SetFixImage(m_mapFilename); + } + + pos.x = 620.0f/640.0f; + pos.y = 460.0f/480.0f; + ddim.x = 20.0f/640.0f; + ddim.y = 20.0f/480.0f; + m_interface->CreateButton(pos, ddim, 11, EVENT_BUTTON_QUIT); + + if ( m_bImmediatSatCom && !bLoading && + m_infoFilename[SATCOM_HUSTON][0] != 0 ) + { + StartDisplayInfo(SATCOM_HUSTON, FALSE); // shows the instructions + } + + m_sound->StopMusic(); + if ( !m_bBase || bLoading ) StartMusic(); + } + + if ( m_phase == PHASE_WIN ) + { + if ( m_endingWinRank == -1 ) + { + ChangePhase(PHASE_TERM); + } + else + { +#if _TEEN + m_bWinTerminate = (m_endingWinRank == 900); + m_dialog->SetSceneName("teenw"); +#else + m_bWinTerminate = (m_endingWinRank == 904); + m_dialog->SetSceneName("win"); +#endif + m_dialog->SetSceneRank(m_endingWinRank); + CreateScene(FALSE, TRUE, FALSE); // sets scene + + pos.x = ox+sx*1; pos.y = oy+sy*1; + ddim.x = dim.x*2; ddim.y = dim.y*2; + m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK); + + if ( m_bWinTerminate ) + { +#if _TEEN + pos.x = ox+sx*3; pos.y = oy+sy*1; + ddim.x = dim.x*15; ddim.y = dim.y*2; + pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0); + pe->SetFontType(FONT_COLOBOT); + pe->SetEditCap(FALSE); + pe->SetHiliteCap(FALSE); + pe->ReadText("help\\teenw.txt"); +#else + pos.x = ox+sx*3; pos.y = oy+sy*0.2f; + ddim.x = dim.x*15; ddim.y = dim.y*3.0f; + pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0); + pe->SetGenericMode(TRUE); + pe->SetFontType(FONT_COLOBOT); + pe->SetEditCap(FALSE); + pe->SetHiliteCap(FALSE); + pe->ReadText("help\\win.txt"); +#endif + } + else + { + m_displayText->DisplayError(INFO_WIN, D3DVECTOR(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f); + } + } + m_sound->StopAll(); + StartMusic(); + } + + if ( m_phase == PHASE_LOST ) + { + if ( m_endingLostRank == -1 ) + { + ChangePhase(PHASE_TERM); + } + else + { + m_bWinTerminate = FALSE; + m_dialog->SetSceneName("lost"); + m_dialog->SetSceneRank(m_endingLostRank); + CreateScene(FALSE, TRUE, FALSE); // sets scene + + pos.x = ox+sx*1; pos.y = oy+sy*1; + ddim.x = dim.x*2; ddim.y = dim.y*2; + m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK); + m_displayText->DisplayError(INFO_LOST, D3DVECTOR(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f); + } + m_sound->StopAll(); + StartMusic(); + } + + if ( m_phase == PHASE_MODEL ) + { + pos.x = ox+sx*0; pos.y = oy+sy*0; + m_interface->CreateButton(pos, dim, 11, EVENT_BUTTON_CANCEL); + + CreateModel(); + } + + if ( m_phase == PHASE_LOADING ) + { + m_engine->SetMouseHide(TRUE); + } + else + { + m_engine->SetMouseHide(FALSE); + } + + m_engine->LoadAllTexture(); +} + + +// Processes an event. + +BOOL CRobotMain::EventProcess(const Event &event) +{ + CEdit* pe; + CObject* pObj; + Event newEvent; + MainMovieType type; + int i; + + if ( event.event == EVENT_FRAME ) + { + if ( !m_movie->EventProcess(event) ) // end of the movie? + { + type = m_movie->RetStopType(); + if ( type == MM_SATCOMopen ) + { + ChangePause(FALSE); + SelectObject(m_infoObject, FALSE); // hands over the command buttons + m_map->ShowMap(m_bMapShow); + m_displayText->HideText(FALSE); + i = m_movieInfoIndex; + StartDisplayInfo(m_movieInfoIndex, FALSE); + m_movieInfoIndex = i; + } + } + + m_dialog->EventProcess(event); + m_displayText->EventProcess(event); + RemoteCamera(m_cameraPan, m_cameraZoom, event.rTime); + + m_interface->EventProcess(event); + if ( m_displayInfo != 0 ) // current edition? + { + m_displayInfo->EventProcess(event); + } + return EventFrame(event); + } + + // Management of the console. +#if 0 + if ( m_phase != PHASE_NAME && + !m_movie->IsExist() && + event.event == EVENT_KEYDOWN && + event.param == VK_PAUSE && + (event.keyState&KS_CONTROL) != 0 ) +#else + if ( m_phase != PHASE_NAME && + !m_movie->IsExist() && + event.event == EVENT_KEYDOWN && + event.param == VK_CANCEL ) // Ctrl+Pause ? +#endif + { + pe = (CEdit*)m_interface->SearchControl(EVENT_CMD); + if ( pe == 0 ) return FALSE; + pe->SetState(STATE_VISIBLE); + pe->SetFocus(TRUE); + if ( m_phase == PHASE_SIMUL ) ChangePause(TRUE); + m_bCmdEdit = TRUE; + return FALSE; + } + if ( event.event == EVENT_KEYDOWN && + event.param == VK_RETURN && m_bCmdEdit ) + { + char cmd[50]; + pe = (CEdit*)m_interface->SearchControl(EVENT_CMD); + if ( pe == 0 ) return FALSE; + pe->GetText(cmd, 50); + pe->SetText(""); + pe->ClearState(STATE_VISIBLE); + if ( m_phase == PHASE_SIMUL ) ChangePause(FALSE); + ExecuteCmd(cmd); + m_bCmdEdit = FALSE; + return FALSE; + } + + // Management of the speed change. + if ( event.event == EVENT_SPEED ) + { + SetSpeed(1.0f); + } + + if ( !m_dialog->EventProcess(event) ) + { + if ( event.event == EVENT_MOUSEMOVE ) + { + m_lastMousePos = event.pos; + HiliteObject(event.pos); + } + return FALSE; + } + + if ( !m_displayText->EventProcess(event) ) + { + return FALSE; + } + + if ( event.event == EVENT_MOUSEMOVE ) + { + m_lastMousePos = event.pos; + HiliteObject(event.pos); + } + + if ( m_displayInfo != 0 ) // current info? + { + m_displayInfo->EventProcess(event); + + if ( event.event == EVENT_KEYDOWN ) + { + if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) || + event.param == m_engine->RetKey(KEYRANK_HELP, 1) || + event.param == m_engine->RetKey(KEYRANK_PROG, 0) || + event.param == m_engine->RetKey(KEYRANK_PROG, 1) || + event.param == VK_ESCAPE ) + { + StopDisplayInfo(); + } + } + if ( event.event == EVENT_OBJECT_INFOOK ) + { + StopDisplayInfo(); + } + return FALSE; + } + + // Simulation phase of the game + if ( m_phase == PHASE_SIMUL ) + { + UpdateInfoText(); + + if ( !m_bEditFull ) + { + m_camera->EventProcess(event); + } + + switch( event.event ) + { + case EVENT_KEYDOWN: + KeyCamera(event.event, event.param); + HiliteClear(); + if ( event.param == VK_F11 ) + { + m_particule->WriteWheelTrace("Savegame\\t.bmp", 256, 256, D3DVECTOR(16.0f, 0.0f, -368.0f), D3DVECTOR(140.0f, 0.0f, -248.0f)); + return FALSE; + } + if ( m_bEditLock ) // current edition? + { + if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) || + event.param == m_engine->RetKey(KEYRANK_HELP, 1) ) + { + StartDisplayInfo(SATCOM_HUSTON, FALSE); + return FALSE; + } + if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) || + event.param == m_engine->RetKey(KEYRANK_PROG, 1) ) + { + StartDisplayInfo(SATCOM_PROG, FALSE); + return FALSE; + } + break; + } + if ( m_bMovieLock ) // current movie? + { + if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) || + event.param == m_engine->RetKey(KEYRANK_QUIT, 1) || + event.param == VK_ESCAPE ) + { + AbortMovie(); + } + return FALSE; + } + if ( m_camera->RetType() == CAMERA_VISIT ) + { + if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) || + event.param == m_engine->RetKey(KEYRANK_VISIT, 1) ) + { + StartDisplayVisit(EVENT_NULL); + } + if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) || + event.param == m_engine->RetKey(KEYRANK_QUIT, 1) || + event.param == VK_ESCAPE ) + { + StopDisplayVisit(); + } + return FALSE; + } + if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) || + event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ) + { + if ( m_movie->IsExist() ) + { + StartDisplayInfo(SATCOM_HUSTON, FALSE); + } + else if ( m_winDelay > 0.0f ) + { + ChangePhase(PHASE_WIN); + } + else if ( m_lostDelay > 0.0f ) + { + ChangePhase(PHASE_LOST); + } + else + { + m_dialog->StartAbort(); // do you want to leave? + } + } + if ( event.param == VK_PAUSE ) + { + if ( !m_bMovieLock && !m_bEditLock && !m_bCmdEdit && + m_camera->RetType() != CAMERA_VISIT && + !m_movie->IsExist() ) + { + ChangePause(!m_engine->RetPause()); + } + } + if ( event.param == m_engine->RetKey(KEYRANK_CAMERA, 0) || + event.param == m_engine->RetKey(KEYRANK_CAMERA, 1) ) + { + ChangeCamera(); + } + if ( event.param == m_engine->RetKey(KEYRANK_DESEL, 0) || + event.param == m_engine->RetKey(KEYRANK_DESEL, 1) ) + { + if ( m_bShortCut ) + { + DeselectObject(); + } + } + if ( event.param == m_engine->RetKey(KEYRANK_HUMAN, 0) || + event.param == m_engine->RetKey(KEYRANK_HUMAN, 1) ) + { + SelectHuman(); + } + if ( event.param == m_engine->RetKey(KEYRANK_NEXT, 0) || + event.param == m_engine->RetKey(KEYRANK_NEXT, 1) ) + { + if ( m_bShortCut ) + { + m_short->SelectNext(); + } + } + if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) || + event.param == m_engine->RetKey(KEYRANK_HELP, 1) ) + { + StartDisplayInfo(SATCOM_HUSTON, TRUE); + } + if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) || + event.param == m_engine->RetKey(KEYRANK_PROG, 1) ) + { + StartDisplayInfo(SATCOM_PROG, TRUE); + } + if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) || + event.param == m_engine->RetKey(KEYRANK_VISIT, 1) ) + { + StartDisplayVisit(EVENT_NULL); + } + if ( event.param == m_engine->RetKey(KEYRANK_SPEED10, 0) || + event.param == m_engine->RetKey(KEYRANK_SPEED10, 1) ) + { + SetSpeed(1.0f); + } + if ( event.param == m_engine->RetKey(KEYRANK_SPEED15, 0) || + event.param == m_engine->RetKey(KEYRANK_SPEED15, 1) ) + { + SetSpeed(1.5f); + } + if ( event.param == m_engine->RetKey(KEYRANK_SPEED20, 0) || + event.param == m_engine->RetKey(KEYRANK_SPEED20, 1) ) + { + SetSpeed(2.0f); + } + if ( event.param == m_engine->RetKey(KEYRANK_SPEED30, 0) || + event.param == m_engine->RetKey(KEYRANK_SPEED30, 1) ) + { + SetSpeed(3.0f); + } + break; + + case EVENT_KEYUP: + KeyCamera(event.event, event.param); + break; + + case EVENT_LBUTTONDOWN: + pObj = DetectObject(event.pos); + if ( !m_bShortCut ) pObj = 0; + if ( pObj != 0 && pObj->RetType() == OBJECT_TOTO ) + { + if ( m_displayInfo != 0 ) // current info? + { + StopDisplayInfo(); + } + else + { + if ( !m_bEditLock ) + { + StartDisplayInfo(SATCOM_HUSTON, TRUE); + } + } + } + else + { + SelectObject(pObj); + } + break; + + case EVENT_LBUTTONUP: + m_cameraPan = 0.0f; + m_cameraZoom = 0.0f; + break; + + case EVENT_BUTTON_QUIT: + if ( m_movie->IsExist() ) + { + StartDisplayInfo(SATCOM_HUSTON, FALSE); + } + else if ( m_winDelay > 0.0f ) + { + ChangePhase(PHASE_WIN); + } + else if ( m_lostDelay > 0.0f ) + { + ChangePhase(PHASE_LOST); + } + else + { + m_dialog->StartAbort(); // do you want to leave? + } + break; + + case EVENT_OBJECT_LIMIT: + StartShowLimit(); + break; + + case EVENT_OBJECT_DESELECT: + if ( m_bShortCut ) + { + DeselectObject(); + } + break; + + case EVENT_OBJECT_HELP: + HelpObject(); + break; + + case EVENT_OBJECT_CAMERA: + ChangeCamera(); + break; + + case EVENT_OBJECT_CAMERAleft: + m_cameraPan = -1.0f; + break; + case EVENT_OBJECT_CAMERAright: + m_cameraPan = 1.0f; + break; + case EVENT_OBJECT_CAMERAnear: + m_cameraZoom = -1.0f; + break; + case EVENT_OBJECT_CAMERAaway: + m_cameraZoom = 1.0f; + break; + + case EVENT_OBJECT_DELETE: + m_dialog->StartDeleteObject(); // do you want to destroy it? + break; + + case EVENT_OBJECT_BHELP: + StartDisplayInfo(SATCOM_HUSTON, TRUE); + break; + + case EVENT_OBJECT_SOLUCE: + StartDisplayInfo(SATCOM_SOLUCE, TRUE); + break; + + case EVENT_OBJECT_MAPZOOM: + m_map->ZoomMap(); + break; + + case EVENT_DT_VISIT0: + case EVENT_DT_VISIT1: + case EVENT_DT_VISIT2: + case EVENT_DT_VISIT3: + case EVENT_DT_VISIT4: + StartDisplayVisit(event.event); + break; + + case EVENT_DT_END: + StopDisplayVisit(); + break; + + case EVENT_OBJECT_SHORTCUT00: + case EVENT_OBJECT_SHORTCUT01: + case EVENT_OBJECT_SHORTCUT02: + case EVENT_OBJECT_SHORTCUT03: + case EVENT_OBJECT_SHORTCUT04: + case EVENT_OBJECT_SHORTCUT05: + case EVENT_OBJECT_SHORTCUT06: + case EVENT_OBJECT_SHORTCUT07: + case EVENT_OBJECT_SHORTCUT08: + case EVENT_OBJECT_SHORTCUT09: + case EVENT_OBJECT_SHORTCUT10: + case EVENT_OBJECT_SHORTCUT11: + case EVENT_OBJECT_SHORTCUT12: + case EVENT_OBJECT_SHORTCUT13: + case EVENT_OBJECT_SHORTCUT14: + case EVENT_OBJECT_SHORTCUT15: + case EVENT_OBJECT_SHORTCUT16: + case EVENT_OBJECT_SHORTCUT17: + case EVENT_OBJECT_SHORTCUT18: + case EVENT_OBJECT_SHORTCUT19: + m_short->SelectShortcut(event.event); + break; + + case EVENT_OBJECT_MOVIELOCK: + AbortMovie(); + break; + + case EVENT_WIN: + ChangePhase(PHASE_WIN); + break; + + case EVENT_LOST: + ChangePhase(PHASE_LOST); + break; + } + + EventObject(event); + return FALSE; + } + + if ( m_phase == PHASE_PERSO ) + { + EventObject(event); + } + + if ( m_phase == PHASE_WIN || + m_phase == PHASE_LOST ) + { + EventObject(event); + + switch( event.event ) + { + case EVENT_KEYDOWN: + if ( event.param == VK_ESCAPE || + event.param == VK_RETURN ) + { + if ( m_bWinTerminate ) + { + ChangePhase(PHASE_INIT); + } + else + { + ChangePhase(PHASE_TERM); + } + } + break; + + case EVENT_BUTTON_OK: + if ( m_bWinTerminate ) + { + ChangePhase(PHASE_INIT); + } + else + { + ChangePhase(PHASE_TERM); + } + break; + } + } + + if ( m_phase == PHASE_MODEL ) + { + switch( event.event ) + { + case EVENT_KEYDOWN: + if ( event.param == VK_ESCAPE ) + { + ChangePhase(PHASE_INIT); + } + if ( event.param == VK_HOME ) + { + InitEye(); + } + break; + + case EVENT_BUTTON_CANCEL: + ChangePhase(PHASE_INIT); + break; + } + + m_model->EventProcess(event); + return FALSE; + } + + return TRUE; +} + + + +// Executes a command. + +void CRobotMain::ExecuteCmd(char *cmd) +{ + if ( cmd[0] == 0 ) return; + + if ( m_phase == PHASE_SIMUL ) + { + if ( strcmp(cmd, "winmission") == 0 ) + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_WIN); + m_event->AddEvent(newEvent); + } + + if ( strcmp(cmd, "lostmission") == 0 ) + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_LOST); + m_event->AddEvent(newEvent); + } + + if ( strcmp(cmd, "trainerpilot") == 0 ) + { + m_bTrainerPilot = !m_bTrainerPilot; + return; + } + + if ( strcmp(cmd, "fly") == 0 ) + { + Event newEvent; + + g_researchDone |= RESEARCH_FLY; + + m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE); + m_event->AddEvent(newEvent); + return; + } + + if ( strcmp(cmd, "allresearch") == 0 ) + { + Event newEvent; + + g_researchDone = -1; // all research are done + + m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE); + m_event->AddEvent(newEvent); + return; + } + + if ( strcmp(cmd, "nolimit") == 0 ) + { + m_terrain->SetFlyingMaxHeight(280.0f); + return; + } + + if ( strcmp(cmd, "photo1") == 0 ) + { + m_bFreePhoto = !m_bFreePhoto; + if ( m_bFreePhoto ) + { + m_camera->SetType(CAMERA_FREE); + ChangePause(TRUE); + } + else + { + m_camera->SetType(CAMERA_BACK); + ChangePause(FALSE); + } + return; + } + + if ( strcmp(cmd, "photo2") == 0 ) + { + m_bFreePhoto = !m_bFreePhoto; + if ( m_bFreePhoto ) + { + m_camera->SetType(CAMERA_FREE); + ChangePause(TRUE); + DeselectAll(); // removes the control buttons + m_map->ShowMap(FALSE); + m_displayText->HideText(TRUE); + } + else + { + m_camera->SetType(CAMERA_BACK); + ChangePause(FALSE); + m_map->ShowMap(m_bMapShow); + m_displayText->HideText(FALSE); + } + return; + } + + if ( strcmp(cmd, "noclip") == 0 ) + { + CObject* object; + + object = RetSelect(); + if ( object != 0 ) + { + object->SetClip(FALSE); + } + return; + } + + if ( strcmp(cmd, "clip") == 0 ) + { + CObject* object; + + object = RetSelect(); + if ( object != 0 ) + { + object->SetClip(TRUE); + } + return; + } + + if ( strcmp(cmd, "addhusky") == 0 ) + { + CObject* object; + + object = RetSelect(); + if ( object != 0 ) + { + object->SetMagnifyDamage(object->RetMagnifyDamage()*0.1f); + } + return; + } + + if ( strcmp(cmd, "addfreezer") == 0 ) + { + CObject* object; + + object = RetSelect(); + if ( object != 0 ) + { + object->SetRange(object->RetRange()*10.0f); + } + return; + } + + if ( strcmp(cmd, "fullpower") == 0 ) + { + CObject* object; + CObject* power; + CPhysics* physics; + + object = RetSelect(); + if ( object != 0 ) + { + power = object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(1.0f); + } + object->SetShield(1.0f); + physics = object->RetPhysics(); + if ( physics != 0 ) + { + physics->SetReactorRange(1.0f); + } + } + return; + } + + if ( strcmp(cmd, "fullenergy") == 0 ) + { + CObject* object; + CObject* power; + + object = RetSelect(); + if ( object != 0 ) + { + power = object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(1.0f); + } + } + return; + } + + if ( strcmp(cmd, "fullshield") == 0 ) + { + CObject* object; + + object = RetSelect(); + if ( object != 0 ) + { + object->SetShield(1.0f); + } + return; + } + + if ( strcmp(cmd, "fullrange") == 0 ) + { + CObject* object; + CPhysics* physics; + + object = RetSelect(); + if ( object != 0 ) + { + physics = object->RetPhysics(); + if ( physics != 0 ) + { + physics->SetReactorRange(1.0f); + } + } + return; + } + } + + if ( strcmp(cmd, "debugmode") == 0 ) + { + m_engine->SetDebugMode(!m_engine->RetDebugMode()); + return; + } + + if ( strcmp(cmd, "showstat") == 0 ) + { + m_engine->SetShowStat(!m_engine->RetShowStat()); + return; + } + + if ( strcmp(cmd, "invshadow") == 0 ) + { + m_engine->SetShadow(!m_engine->RetShadow()); + return; + } + + if ( strcmp(cmd, "invdirty") == 0 ) + { + m_engine->SetDirty(!m_engine->RetDirty()); + return; + } + + if ( strcmp(cmd, "invfog") == 0 ) + { + m_engine->SetFog(!m_engine->RetFog()); + return; + } + + if ( strcmp(cmd, "invlens") == 0 ) + { + m_engine->SetLensMode(!m_engine->RetLensMode()); + return; + } + + if ( strcmp(cmd, "invwater") == 0 ) + { + m_engine->SetWaterMode(!m_engine->RetWaterMode()); + return; + } + + if ( strcmp(cmd, "invsky") == 0 ) + { + m_engine->SetSkyMode(!m_engine->RetSkyMode()); + return; + } + + if ( strcmp(cmd, "invplanet") == 0 ) + { + m_engine->SetPlanetMode(!m_engine->RetPlanetMode()); + return; + } + + if ( strcmp(cmd, "showpos") == 0 ) + { + m_bShowPos = !m_bShowPos; + return; + } + + if ( strcmp(cmd, "selectinsect") == 0 ) + { + m_bSelectInsect = !m_bSelectInsect; + return; + } + + if ( strcmp(cmd, "showsoluce") == 0 ) + { + m_bShowSoluce = !m_bShowSoluce; + m_dialog->ShowSoluceUpdate(); + return; + } + +#if _TEEN + if ( strcmp(cmd, "allteens") == 0 ) +#else + if ( strcmp(cmd, "allmission") == 0 ) +#endif + { + m_bShowAll = !m_bShowAll; + m_dialog->AllMissionUpdate(); + return; + } + + if ( strcmp(cmd, "invradar") == 0 ) + { + m_bCheatRadar = !m_bCheatRadar; + return; + } + + if ( m_phase == PHASE_SIMUL ) + { + m_displayText->DisplayError(ERR_CMD, D3DVECTOR(0.0f,0.0f,0.0f)); + } +} + + + +// Returns the type of current movie. + +MainMovieType CRobotMain::RetMainMovie() +{ + return m_movie->RetType(); +} + + +// Clears the display of instructions. + +void CRobotMain::FlushDisplayInfo() +{ + int i; + + for ( i=0 ; iRetType() == OBJECT_HUMAN ); + + if ( !m_bEditLock && bMovie && !m_movie->IsExist() && bHuman ) + { + motion = pObj->RetMotion(); + if ( motion != 0 && motion->RetAction() == -1 ) + { + m_movieInfoIndex = index; + m_movie->Start(MM_SATCOMopen, 2.5f); + ChangePause(TRUE); +//? m_map->ShowMap(FALSE); + m_infoObject = DeselectAll(); // removes the control buttons + m_displayText->HideText(TRUE); + return; + } + } + + if ( m_movie->IsExist() ) + { + m_movie->Stop(); + ChangePause(FALSE); + SelectObject(m_infoObject, FALSE); // hands over the command buttons +//? m_map->ShowMap(m_bMapShow); + m_displayText->HideText(FALSE); + } + + StartDisplayInfo(m_infoFilename[index], index); +} + +// Beginning of the displaying of instructions. + +void CRobotMain::StartDisplayInfo(char *filename, int index) +{ + CButton* pb; + BOOL bSoluce; + + if ( m_bCmdEdit ) return; + + m_movieInfoIndex = -1; + ClearInterface(); // removes setting evidence and tooltip + + if ( !m_bEditLock ) + { +//? m_map->ShowMap(FALSE); + m_infoObject = DeselectAll(); // removes the control buttons + m_displayText->HideText(TRUE); + m_sound->MuteAll(TRUE); + } + + pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT); + if ( pb != 0 ) + { + pb->ClearState(STATE_VISIBLE); + } + + bSoluce = m_dialog->RetSceneSoluce(); + + m_displayInfo = new CDisplayInfo(m_iMan); + m_displayInfo->StartDisplayInfo(filename, index, bSoluce); + + m_infoIndex = index; + if ( index != -1 ) + { + m_displayInfo->SetPosition(m_infoPos[index]); + } +} + +// End of displaying of instructions. + +void CRobotMain::StopDisplayInfo() +{ + CButton* pb; + + if ( m_movieInfoIndex != -1 ) // film to read the SatCom? + { + m_movie->Start(MM_SATCOMclose, 2.0f); + } + + if ( m_infoIndex != -1 ) + { + m_infoPos[m_infoIndex] = m_displayInfo->RetPosition(); + } + m_displayInfo->StopDisplayInfo(); + + delete m_displayInfo; + m_displayInfo = 0; + + if ( !m_bEditLock ) + { + pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT); + if ( pb != 0 ) + { + pb->SetState(STATE_VISIBLE); + } + + SelectObject(m_infoObject, FALSE); // gives the command buttons +//? m_map->ShowMap(m_bMapShow); + m_displayText->HideText(FALSE); + + m_sound->MuteAll(FALSE); + } + + if ( m_infoUsed == 0 ) + { + m_displayText->ClearText(); // removes message "see SatCom ..." + } + m_infoUsed ++; +} + +// Returns the name of the text display. + +char* CRobotMain::RetDisplayInfoName(int index) +{ + return m_infoFilename[index]; +} + +// Returns the name of the text display. + +int CRobotMain::RetDisplayInfoPosition(int index) +{ + return m_infoPos[index]; +} + +// Returns the name of the text display. + +void CRobotMain::SetDisplayInfoPosition(int index, int pos) +{ + m_infoPos[index] = pos; +} + + +// Beginning of a dialogue during the game, + +void CRobotMain::StartSuspend() +{ + CButton* pb; + + m_map->ShowMap(FALSE); + m_infoObject = DeselectAll(); // removes the control buttons + m_displayText->HideText(TRUE); + + pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT); + if ( pb != 0 ) + { + pb->ClearState(STATE_VISIBLE); + } + + m_bSuspend = TRUE; +} + +// End of dialogue during the game, + +void CRobotMain::StopSuspend() +{ + CButton* pb; + + pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT); + if ( pb != 0 ) + { + pb->SetState(STATE_VISIBLE); + } + + SelectObject(m_infoObject, FALSE); // gives the command buttons + m_map->ShowMap(m_bMapShow); + m_displayText->HideText(FALSE); + + m_bSuspend = FALSE; +} + + +// Returns the absolute time of the game + +float CRobotMain::RetGameTime() +{ + return m_gameTime; +} + + + +// Managing the size of the default fonts. + +void CRobotMain::SetFontSize(float size) +{ + m_fontSize = size; + SetProfileFloat("Edit", "FontSize", m_fontSize); +} + +float CRobotMain::RetFontSize() +{ + return m_fontSize; +} + +// Managing the size of the default window. + +void CRobotMain::SetWindowPos(FPOINT pos) +{ + m_windowPos = pos; + SetProfileFloat("Edit", "WindowPos.x", m_windowPos.x); + SetProfileFloat("Edit", "WindowPos.y", m_windowPos.y); +} + +FPOINT CRobotMain::RetWindowPos() +{ + return m_windowPos; +} + +void CRobotMain::SetWindowDim(FPOINT dim) +{ + m_windowDim = dim; + SetProfileFloat("Edit", "WindowDim.x", m_windowDim.x); + SetProfileFloat("Edit", "WindowDim.y", m_windowDim.y); +} + +FPOINT CRobotMain::RetWindowDim() +{ + return m_windowDim; +} + + +// Managing windows open/save. + +void CRobotMain::SetIOPublic(BOOL bMode) +{ + m_IOPublic = bMode; + SetProfileInt("Edit", "IOPublic", m_IOPublic); +} + +BOOL CRobotMain::RetIOPublic() +{ + return m_IOPublic; +} + +void CRobotMain::SetIOPos(FPOINT pos) +{ + m_IOPos = pos; + SetProfileFloat("Edit", "IOPos.x", m_IOPos.x); + SetProfileFloat("Edit", "IOPos.y", m_IOPos.y); +} + +FPOINT CRobotMain::RetIOPos() +{ + return m_IOPos; +} + +void CRobotMain::SetIODim(FPOINT dim) +{ + m_IODim = dim; + SetProfileFloat("Edit", "IODim.x", m_IODim.x); + SetProfileFloat("Edit", "IODim.y", m_IODim.y); +} + +FPOINT CRobotMain::RetIODim() +{ + return m_IODim; +} + + + +// Start of the visit instead of an error. + +void CRobotMain::StartDisplayVisit(EventMsg event) +{ + CWindow* pw; + CButton* button; + CGroup* group; + D3DVECTOR goal; + FPOINT pos, dim; + int i, j; + + if ( m_bEditLock ) return; + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2); + if ( pw == 0 ) return; + + if ( event == EVENT_NULL ) // visit by keyboard shortcut? + { + if ( m_visitLast != EVENT_NULL ) // already a current visit? + { + i = m_visitLast-EVENT_DT_VISIT0; + } + else + { + i = MAXDTLINE; + } + + // Seeks the last. + for ( j=0 ; jSearchControl(EventMsg(EVENT_DT_VISIT0+i)); + if ( button == 0 || !button->TestState(STATE_ENABLE) ) continue; + + group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i)); + if ( group != 0 ) + { + event = EventMsg(EVENT_DT_VISIT0+i); + break; + } + } + } + if ( event == EVENT_NULL ) + { + m_sound->Play(SOUND_TZOING); // nothing to do! + return; + } + + m_visitLast = event; + + ClearInterface(); // removes setting evidence and tooltip + + if ( m_camera->RetType() == CAMERA_VISIT ) // already a current visit? + { + m_camera->StopVisit(); + m_displayText->ClearVisit(); + } + else + { + m_visitObject = DeselectAll(); // removes the control buttons + } + + // Creates the "continue" button. + if ( m_interface->SearchControl(EVENT_DT_END) == 0 ) + { + pos.x = 10.0f/640.0f; + pos.y = 10.0f/480.0f; + dim.x = 50.0f/640.0f; + dim.y = 50.0f/480.0f; + m_interface->CreateButton(pos, dim, 16, EVENT_DT_END); + } + + // Creates the arrow to show the place. + if ( m_visitArrow != 0 ) + { + m_visitArrow->DeleteObject(); + delete m_visitArrow; + m_visitArrow = 0; + } + goal = m_displayText->RetVisitGoal(event); + m_visitArrow = CreateObject(goal, 0.0f, 1.0f, 10.0f, OBJECT_SHOW, FALSE, FALSE, 0); + + m_visitPos = m_visitArrow->RetPosition(0); + m_visitPosArrow = m_visitPos; + m_visitPosArrow.y += m_displayText->RetVisitHeight(event); + m_visitArrow->SetPosition(0, m_visitPosArrow); + + m_visitTime = 0.0; + m_visitParticule = 0.0f; + + m_particule->DeleteParticule(PARTISHOW); + + m_camera->StartVisit(m_displayText->RetVisitGoal(event), + m_displayText->RetVisitDist(event)); + m_displayText->SetVisit(event); + ChangePause(TRUE); +} + +// Move the arrow to visit. + +void CRobotMain::FrameVisit(float rTime) +{ + D3DVECTOR pos, speed; + FPOINT dim; + float level; + + if ( m_visitArrow == 0 ) return; + + // Moves the arrow. + m_visitTime += rTime; + + pos = m_visitPosArrow; + pos.y += 1.5f+sinf(m_visitTime*4.0f)*4.0f; + m_visitArrow->SetPosition(0, pos); + m_visitArrow->SetAngleY(0, m_visitTime*2.0f); + + // Manages the particles "arrows". + m_visitParticule -= rTime; + if ( m_visitParticule <= 0.0f ) + { + m_visitParticule = 1.5f; + + pos = m_visitPos; + level = m_terrain->RetFloorLevel(pos)+2.0f; + if ( pos.y < level ) pos.y = level; // not below the ground + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 30.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISHOW, 2.0f); + } +} + +// End of the visit instead of an error. + +void CRobotMain::StopDisplayVisit() +{ + m_visitLast = EVENT_NULL; + + // Removes the button. + m_interface->DeleteControl(EVENT_DT_END); + + // Removes the arrow. + if ( m_visitArrow != 0 ) + { + m_visitArrow->DeleteObject(); + delete m_visitArrow; + m_visitArrow = 0; + } + + // Removes particles "arrows". + m_particule->DeleteParticule(PARTISHOW); + + m_camera->StopVisit(); + m_displayText->ClearVisit(); + ChangePause(FALSE); + if ( m_visitObject != 0 ) + { + SelectObject(m_visitObject, FALSE); // gives the command buttons + m_visitObject = 0; + } +} + + + +// Updates all the shortcuts. + +void CRobotMain::UpdateShortcuts() +{ + m_short->UpdateShortcuts(); +} + +// Returns the object that default was select after the creation of a scene. + +CObject* CRobotMain::RetSelectObject() +{ + if ( m_selectObject != 0 ) return m_selectObject; + return SearchHuman(); +} + +// Deselects everything, and returns the object that was selected. + +CObject* CRobotMain::DeselectAll() +{ + CObject* pObj; + CObject* pPrev; + int i; + + pPrev = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetSelect() ) pPrev = pObj; + pObj->SetSelect(FALSE); + } + return pPrev; +} + +// Selects an object, without attending to deselect the rest. + +void CRobotMain::SelectOneObject(CObject* pObj, BOOL bDisplayError) +{ + ObjectType type; + CObject* toto; + CMotionToto* mt; + + pObj->SetSelect(TRUE, bDisplayError); + m_camera->SetObject(pObj); + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || + type == OBJECT_APOLLO2 ) + { + m_camera->SetType(pObj->RetCameraType()); + m_camera->SetDist(pObj->RetCameraDist()); + } + else + { + m_camera->SetType(CAMERA_BACK); + } + + toto = SearchToto(); + if ( toto != 0 ) + { + mt = (CMotionToto*)toto->RetMotion(); + if ( mt != 0 ) + { + mt->SetLinkType(type); + } + } +} + +// Selects the object aimed by the mouse. + +BOOL CRobotMain::SelectObject(CObject* pObj, BOOL bDisplayError) +{ + CObject* pPrev; + + if ( m_camera->RetType() == CAMERA_VISIT ) + { + StopDisplayVisit(); + } + + if ( m_bMovieLock || m_bEditLock || m_bPause ) return FALSE; + if ( m_movie->IsExist() ) return FALSE; + if ( pObj == 0 || !IsSelectable(pObj) ) return FALSE; + + pPrev = DeselectAll(); + + if ( pPrev != 0 && pPrev != pObj ) + { + pObj->AddDeselList(pPrev); + } + + SelectOneObject(pObj, bDisplayError); + m_short->UpdateShortcuts(); + return TRUE; +} + +// Deselects the selected object. + +BOOL CRobotMain::DeselectObject() +{ + CObject* pObj; + CObject* pPrev; + + pPrev = DeselectAll(); + + if ( pPrev == 0 ) + { + pObj = SearchHuman(); + } + else + { + pObj = pPrev->SubDeselList(); + } + if ( pObj == 0 ) + { + pObj = SearchHuman(); + } + + if ( pObj != 0 ) + { + SelectOneObject(pObj); + } + else + { + m_camera->SetType(CAMERA_FREE); + } + + m_short->UpdateShortcuts(); + return TRUE; +} + +// Quickly removes all objects. + +void CRobotMain::DeleteAllObjects() +{ + CPyro* pyro; + CObject* pObj; + int i; + + // Removes all pyrotechnic effects in progress. + while ( TRUE ) + { + pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0); + if ( pyro == 0 ) break; + + pyro->DeleteObject(); + delete pyro; + } + + // Removes the arrow. + if ( m_visitArrow != 0 ) + { + m_visitArrow->DeleteObject(); + delete m_visitArrow; + m_visitArrow = 0; + } + + for ( i=0 ; iSearchInstance(CLASS_OBJECT, 0); + if ( pObj == 0 ) break; + + pObj->DeleteObject(TRUE); // destroys rapidly + delete pObj; + } +} + +// Selects the human. + +void CRobotMain::SelectHuman() +{ + SelectObject(SearchHuman()); +} + +// Returns the object human. + +CObject* CRobotMain::SearchHuman() +{ + ObjectType type; + CObject* pObj; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) + { + return pObj; + } + } + return 0; +} + +// Returns the object toto. + +CObject* CRobotMain::SearchToto() +{ + ObjectType type; + CObject* pObj; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_TOTO ) + { + return pObj; + } + } + return 0; +} + +// Returns the nearest selectable object from a given position. + +CObject* CRobotMain::SearchNearest(D3DVECTOR pos, CObject* pExclu) +{ + ObjectType type; + CObject *pObj, *pBest; + D3DVECTOR oPos; + float min, dist; + int i; + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == pExclu ) continue; + if ( !IsSelectable(pObj) ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_TOTO ) continue; + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, pos); + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + return pBest; +} + +// Returns the selected object. + +CObject* CRobotMain::RetSelect() +{ + CObject* pObj; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetSelect() ) + { + return pObj; + } + } + return 0; +} + +CObject* CRobotMain::SearchObject(ObjectType type) +{ + CObject* pObj; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetType() == type ) + { + return pObj; + } + } + return 0; +} + +// Detects the object aimed by the mouse. + +CObject* CRobotMain::DetectObject(FPOINT pos) +{ + ObjectType type; + CObject *pObj, *pTarget; + int objRank, i, j, rank; + + objRank = m_engine->DetectObject(pos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + if ( pObj->RetProxyActivate() ) continue; + + pTarget = 0; + type = pObj->RetType(); + if ( type == OBJECT_PORTICO || + type == OBJECT_BASE || + type == OBJECT_DERRICK || + type == OBJECT_FACTORY || + type == OBJECT_REPAIR || + type == OBJECT_DESTROYER || + type == OBJECT_STATION || + type == OBJECT_CONVERT || + type == OBJECT_TOWER || + type == OBJECT_RESEARCH || + type == OBJECT_RADAR || + type == OBJECT_INFO || + type == OBJECT_ENERGY || + type == OBJECT_LABO || + type == OBJECT_NUCLEAR || + type == OBJECT_PARA || + type == OBJECT_SAFE || + type == OBJECT_HUSTON || + type == OBJECT_TARGET1 || + type == OBJECT_TARGET2 || + type == OBJECT_START || + type == OBJECT_END || + type == OBJECT_STONE || + type == OBJECT_URANIUM || + type == OBJECT_BULLET || + type == OBJECT_METAL || + type == OBJECT_BBOX || + type == OBJECT_KEYa || + type == OBJECT_KEYb || + type == OBJECT_KEYc || + type == OBJECT_KEYd || + type == OBJECT_TNT || + type == OBJECT_SCRAP1 || + type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 || + type == OBJECT_SCRAP4 || + type == OBJECT_SCRAP5 || + type == OBJECT_BOMB || + type == OBJECT_BAG || + type == OBJECT_WAYPOINT || + type == OBJECT_FLAGb || + type == OBJECT_FLAGr || + type == OBJECT_FLAGg || + type == OBJECT_FLAGy || + type == OBJECT_FLAGv || + type == OBJECT_MARKPOWER || + type == OBJECT_MARKSTONE || + type == OBJECT_MARKURANIUM || + type == OBJECT_MARKKEYa || + type == OBJECT_MARKKEYb || + type == OBJECT_MARKKEYc || + type == OBJECT_MARKKEYd || + type == OBJECT_HUMAN || + type == OBJECT_TECH || + type == OBJECT_TOTO || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || + type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM || + type == OBJECT_EGG || + type == OBJECT_RUINmobilew1 || + type == OBJECT_RUINmobilew2 || + type == OBJECT_RUINmobilet1 || + type == OBJECT_RUINmobilet2 || + type == OBJECT_RUINmobiler1 || + type == OBJECT_RUINmobiler2 || + type == OBJECT_RUINfactory || + type == OBJECT_RUINdoor || + type == OBJECT_RUINsupport || + type == OBJECT_RUINradar || + type == OBJECT_RUINconvert || + type == OBJECT_RUINbase || + type == OBJECT_RUINhead || + type == OBJECT_APOLLO1 || + type == OBJECT_APOLLO2 || + type == OBJECT_APOLLO3 || + type == OBJECT_APOLLO4 || + type == OBJECT_APOLLO5 ) + { + pTarget = pObj; + } + else if ( (type == OBJECT_POWER || + type == OBJECT_ATOMIC ) && + pObj->RetTruck() != 0 ) // battery used? + { + pTarget = pObj->RetTruck(); + } + else if ( type == OBJECT_POWER || + type == OBJECT_ATOMIC ) + { + pTarget = pObj; + } + + for ( j=0 ; jRetObjectRank(j); + if ( rank == -1 ) continue; + if ( rank != objRank ) continue; + return pTarget; + } + } + return 0; +} + +// Indicates whether an object is selectable. + +BOOL CRobotMain::IsSelectable(CObject* pObj) +{ + ObjectType type; + + if ( !pObj->RetSelectable() ) return FALSE; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN || + type == OBJECT_TOTO || + type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr || + type == OBJECT_APOLLO2 || + type == OBJECT_BASE || + type == OBJECT_DERRICK || + type == OBJECT_FACTORY || + type == OBJECT_REPAIR || + type == OBJECT_DESTROYER|| + type == OBJECT_STATION || + type == OBJECT_CONVERT || + type == OBJECT_TOWER || + type == OBJECT_RESEARCH || + type == OBJECT_RADAR || + type == OBJECT_INFO || + type == OBJECT_ENERGY || + type == OBJECT_LABO || + type == OBJECT_NUCLEAR || + type == OBJECT_PARA || + type == OBJECT_SAFE || + type == OBJECT_HUSTON ) + { + return TRUE; + } + + if ( m_bSelectInsect ) + { + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM || + type == OBJECT_MOBILEtg ) + { + return TRUE; + } + } + + return FALSE; +} + + +// Deletes the selected object. + +BOOL CRobotMain::DeleteObject() +{ + CObject* pObj; + CPyro* pyro; + + pObj = RetSelect(); + if ( pObj == 0 ) return FALSE; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_FRAGT, pObj); + + pObj->SetSelect(FALSE); // deselects the object + m_camera->SetType(CAMERA_EXPLO); + DeselectAll(); + pObj->DeleteDeselList(pObj); + + return TRUE; +} + + +// Removes setting evidence of the object with the mouse hovers over. + +void CRobotMain::HiliteClear() +{ + CObject* pObj; + int i; + + ClearTooltip(); + m_tooltipName[0] = 0; // really removes the tooltip + + if ( !m_bHilite ) return; + + i = -1; + m_engine->SetHiliteRank(&i); // nothing more selected + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + pObj->SetHilite(FALSE); + m_map->SetHilite(0); + m_short->SetHilite(0); + } + + m_bHilite = FALSE; +} + +// Highlights the object with the mouse hovers over. + +void CRobotMain::HiliteObject(FPOINT pos) +{ + CObject* pObj; + char name[100]; + BOOL bInMap; + + if ( m_bFixScene && m_phase != PHASE_PERSO ) return; + if ( m_bMovieLock ) return; + if ( m_movie->IsExist() ) return; + if ( m_engine->RetMouseHide() ) return; + + ClearInterface(); // removes setting evidence and tooltip + + pObj = m_short->DetectShort(pos); + + if ( m_dialog->RetTooltip() && m_interface->GetTooltip(pos, name) ) + { + m_tooltipPos = pos; + strcpy(m_tooltipName, name); + m_tooltipTime = 0.0f; + if ( pObj == 0 ) return; + } + + if ( m_bSuspend ) return; + + if ( pObj == 0 ) + { + pObj = m_map->DetectMap(pos, bInMap); + if ( pObj == 0 ) + { + if ( bInMap ) return; + + pObj = DetectObject(pos); + + if ( m_camera->RetType() == CAMERA_ONBOARD && + m_camera->RetObject() == pObj ) + { + return; + } + } + } + + if ( pObj != 0 ) + { + if ( m_dialog->RetTooltip() && pObj->GetTooltipName(name) ) + { + m_tooltipPos = pos; + strcpy(m_tooltipName, name); + m_tooltipTime = 0.0f; + } + + if ( IsSelectable(pObj) ) + { + pObj->SetHilite(TRUE); + m_map->SetHilite(pObj); + m_short->SetHilite(pObj); + m_bHilite = TRUE; + } + } +} + +// Highlights the object with the mouse hovers over. + +void CRobotMain::HiliteFrame(float rTime) +{ + if ( m_bFixScene && m_phase != PHASE_PERSO ) return; + if ( m_bMovieLock ) return; + if ( m_movie->IsExist() ) return; + + m_tooltipTime += rTime; + + ClearTooltip(); + + if ( m_tooltipTime >= 0.2f && + m_tooltipName[0] != 0 ) + { + CreateTooltip(m_tooltipPos, m_tooltipName); + } +} + +// Creates a tooltip. + +void CRobotMain::CreateTooltip(FPOINT pos, char* text) +{ + CWindow* pw; + FPOINT start, end, dim, offset, corner; + + corner.x = pos.x+0.022f; + corner.y = pos.y-0.052f; + + m_engine->RetText()->DimText(text, corner, 1, + SMALLFONT, NORMSTRETCH, FONT_COLOBOT, + start, end); + start.x -= 0.010f; + start.y -= 0.002f; + end.x += 0.010f; + end.y += 0.004f; // ch'tite (?) margin + + pos.x = start.x; + pos.y = start.y; + dim.x = end.x-start.x; + dim.y = end.y-start.y; + + offset.x = 0.0f; + offset.y = 0.0f; + if ( pos.x+dim.x > 1.0f ) offset.x = 1.0f-(pos.x+dim.x); + if ( pos.y < 0.0f ) offset.y = -pos.y; + + corner.x += offset.x; + corner.y += offset.y; + pos.x += offset.x; + pos.y += offset.y; + + m_interface->CreateWindows(pos, dim, 1, EVENT_TOOLTIP); + + pw = (CWindow*)m_interface->SearchControl(EVENT_TOOLTIP); + if ( pw != 0 ) + { + pw->SetState(STATE_SHADOW); + pw->SetTrashEvent(FALSE); + + pos.y -= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT)/2.0f; + pw->CreateLabel(pos, dim, -1, EVENT_LABEL2, text); + } +} + +// Clears the previous tooltip. + +void CRobotMain::ClearTooltip() +{ + m_interface->DeleteControl(EVENT_TOOLTIP); +} + + +// Displays help for an object. + +void CRobotMain::HelpObject() +{ + CObject* pObj; + char* filename; + + pObj = RetSelect(); + if ( pObj == 0 ) return; + + filename = RetHelpFilename(pObj->RetType()); + if ( filename[0] == 0 ) return; + + StartDisplayInfo(filename, -1); +} + + +// Change the mode of the camera. + +void CRobotMain::ChangeCamera() +{ + CObject* pObj; + ObjectType oType; + CameraType type; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetSelect() ) + { + if ( pObj->RetCameraLock() ) return; + + oType = pObj->RetType(); + type = pObj->RetCameraType(); + + if ( oType != OBJECT_MOBILEfa && + oType != OBJECT_MOBILEta && + oType != OBJECT_MOBILEwa && + oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfc && + oType != OBJECT_MOBILEtc && + oType != OBJECT_MOBILEwc && + oType != OBJECT_MOBILEic && + oType != OBJECT_MOBILEfi && + oType != OBJECT_MOBILEti && + oType != OBJECT_MOBILEwi && + oType != OBJECT_MOBILEii && + oType != OBJECT_MOBILEfs && + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_MOBILErt && + oType != OBJECT_MOBILErc && + oType != OBJECT_MOBILErr && + oType != OBJECT_MOBILErs && + oType != OBJECT_MOBILEsa && + oType != OBJECT_MOBILEtg && + oType != OBJECT_MOBILEft && + oType != OBJECT_MOBILEtt && + oType != OBJECT_MOBILEwt && + oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILEdr && + oType != OBJECT_APOLLO2 ) return; + + if ( oType == OBJECT_MOBILEdr ) // designer? + { + if ( type == CAMERA_PLANE ) type = CAMERA_BACK; + else if ( type == CAMERA_BACK ) type = CAMERA_PLANE; + } + else if ( pObj->RetTrainer() ) // trainer? + { + if ( type == CAMERA_ONBOARD ) type = CAMERA_FIX; + else if ( type == CAMERA_FIX ) type = CAMERA_PLANE; + else if ( type == CAMERA_PLANE ) type = CAMERA_BACK; + else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD; + } + else + { + if ( type == CAMERA_ONBOARD ) type = CAMERA_BACK; + else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD; + } + + pObj->SetCameraType(type); + m_camera->SetType(type); + } + } +} + +// Remote control the camera using the arrow keys. + +void CRobotMain::KeyCamera(EventMsg event, long param) +{ + CObject* pObj; + + if ( event == EVENT_KEYUP ) + { + if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) || + param == m_engine->RetKey(KEYRANK_LEFT, 1) ) + { + m_cameraPan = 0.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) || + param == m_engine->RetKey(KEYRANK_RIGHT, 1) ) + { + m_cameraPan = 0.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_UP, 0) || + param == m_engine->RetKey(KEYRANK_UP, 1) ) + { + m_cameraZoom = 0.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) || + param == m_engine->RetKey(KEYRANK_DOWN, 1) ) + { + m_cameraZoom = 0.0f; + } + } + + if ( m_phase != PHASE_SIMUL ) return; + if ( m_bEditLock ) return; // current edition? + if ( m_bTrainerPilot ) return; + + pObj = RetSelect(); + if ( pObj == 0 ) return; + if ( !pObj->RetTrainer() ) return; + + if ( event == EVENT_KEYDOWN ) + { + if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) || + param == m_engine->RetKey(KEYRANK_LEFT, 1) ) + { + m_cameraPan = -1.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) || + param == m_engine->RetKey(KEYRANK_RIGHT, 1) ) + { + m_cameraPan = 1.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_UP, 0) || + param == m_engine->RetKey(KEYRANK_UP, 1) ) + { + m_cameraZoom = -1.0f; + } + + if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) || + param == m_engine->RetKey(KEYRANK_DOWN, 1) ) + { + m_cameraZoom = 1.0f; + } + } +} + +// Panned with the camera if a button is pressed. + +void CRobotMain::RemoteCamera(float pan, float zoom, float rTime) +{ + float value; + + if ( pan != 0.0f ) + { + value = m_camera->RetRemotePan(); + value += pan*rTime*1.5f; + m_camera->SetRemotePan(value); + } + + if ( zoom != 0.0f ) + { + value = m_camera->RetRemoteZoom(); + value += zoom*rTime*0.3f; + m_camera->SetRemoteZoom(value); + } +} + + + +// Cancels the current movie. + +void CRobotMain::AbortMovie() +{ + CObject* pObj; + CAuto* automat; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + automat = pObj->RetAuto(); + if ( automat != 0 ) + { + automat->Abort(); + } + } + + m_engine->SetMouseHide(FALSE); +} + + + +// Updates the text information. + +void CRobotMain::UpdateInfoText() +{ + CObject* pObj; + D3DVECTOR pos; + char info[100]; + + if ( m_bShowPos ) + { + pObj = RetSelect(); + if ( pObj != 0 ) + { + pos = pObj->RetPosition(0); + sprintf(info, "Pos = %.2f ; %.2f", pos.x/g_unit, pos.z/g_unit); + m_engine->SetInfoText(4, info); + } + } +} + + +// Initializes the view. + +void CRobotMain::InitEye() +{ + if ( m_phase == PHASE_SIMUL ) + { + m_camera->Init(D3DVECTOR( 0.0f, 10.0f, 0.0f), + D3DVECTOR(10.0f, 5.0f, 0.0f), 0.0f); + } + + if ( m_phase == PHASE_MODEL ) + { + m_model->InitView(); + } +} + +// Advances the entire scene. + +BOOL CRobotMain::EventFrame(const Event &event) +{ + ObjectType type; + CObject *pObj, *toto; + CPyro* pPyro; + CWindow* pw; + CMap* pm; + int i; + + m_time += event.rTime; + if ( !m_bMovieLock ) m_gameTime += event.rTime; + + if ( !m_bImmediatSatCom && !m_bBeginSatCom && + m_gameTime > 0.1f && m_phase == PHASE_SIMUL ) + { + m_displayText->DisplayError(INFO_BEGINSATCOM, D3DVECTOR(0.0f,0.0f,0.0f)); + m_bBeginSatCom = TRUE; // message appears + } + + m_water->EventProcess(event); + m_cloud->EventProcess(event); + m_blitz->EventProcess(event); + m_planet->EventProcess(event); + + pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1); + if ( pw == 0 ) + { + pm = 0; + } + else + { + pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP); + if ( pm != 0 ) pm->FlushObject(); + } + + toto = 0; + if ( !m_bFreePhoto ) + { + // Advances all the robots, but not toto. + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pm != 0 ) pm->UpdateObject(pObj); + if ( pObj->RetTruck() != 0 ) continue; + type = pObj->RetType(); + if ( type == OBJECT_TOTO ) + { + toto = pObj; + } + else + { + pObj->EventProcess(event); + } + } + // Advances all objects transported by robots. + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj->RetTruck() == 0 ) continue; + pObj->EventProcess(event); + } + + // Advances pyrotechnic effects. + for ( i=0 ; i<1000000 ; i++ ) + { + pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i); + if ( pPyro == 0 ) break; + + pPyro->EventProcess(event); + if ( pPyro->IsEnded() != ERR_CONTINUE ) + { + pPyro->DeleteObject(); + delete pPyro; + } + } + } + + // The camera follows the object, because its position + // may depend on the selected object (CAMERA_ONBOARD or CAMERA_BACK). + if ( m_phase == PHASE_SIMUL && !m_bEditFull ) + { + m_camera->EventProcess(event); + + if ( m_engine->RetFog() ) + { + m_camera->SetOverBaseColor(m_particule->RetFogColor(m_engine->RetEyePt())); + } + } + if ( m_phase == PHASE_PERSO || + m_phase == PHASE_WIN || + m_phase == PHASE_LOST ) + { + m_camera->EventProcess(event); + } + + // Advances toto following the camera, because its position depends on the camera. + if ( toto != 0 ) + { + toto->EventProcess(event); + } + + // Advances model. + if ( m_phase == PHASE_MODEL ) + { + m_model->ViewMove(event, 2.0f); + m_model->UpdateView(); + m_model->EventProcess(event); + } + + HiliteFrame(event.rTime); + + // Moves the film indicator. + if ( m_bMovieLock && !m_bEditLock ) // movie in progress? + { + CControl* pc; + FPOINT pos, dim; + float zoom; + + pc = m_interface->SearchControl(EVENT_OBJECT_MOVIELOCK); + if ( pc != 0 ) + { + dim.x = 32.0f/640.0f; + dim.y = 32.0f/480.0f; + pos.x = 20.0f/640.0f; + pos.y = (480.0f-24.0f)/480.0f; + + zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1 + dim.x *= zoom; + dim.y *= zoom; + pos.x -= dim.x/2.0f; + pos.y -= dim.y/2.0f; + + pc->SetPos(pos); + pc->SetDim(dim); + } + } + + // Moves edition indicator. + if ( m_bEditLock || m_bPause ) // edition in progress? + { + CControl* pc; + FPOINT pos, dim; + float zoom; + + pc = m_interface->SearchControl(EVENT_OBJECT_EDITLOCK); + if ( pc != 0 ) + { + if ( m_bEditFull || m_bEditLock ) + { + dim.x = 10.0f/640.0f; + dim.y = 10.0f/480.0f; + pos.x = -20.0f/640.0f; + pos.y = -20.0f/480.0f; // invisible! + } + else + { + dim.x = 32.0f/640.0f; + dim.y = 32.0f/480.0f; + pos.x = 20.0f/640.0f; + pos.y = (480.0f-24.0f)/480.0f; + + zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1 + dim.x *= zoom; + dim.y *= zoom; + pos.x -= dim.x/2.0f; + pos.y -= dim.y/2.0f; + } + pc->SetPos(pos); + pc->SetDim(dim); + } + } + + // Will move the arrow to visit. + if ( m_camera->RetType() == CAMERA_VISIT ) + { + FrameVisit(event.rTime); + } + + // Moves the boundaries. + FrameShowLimit(event.rTime); + + if ( m_phase == PHASE_SIMUL ) + { + if ( !m_bEditLock && m_checkEndTime+1.0f < m_time ) + { + m_checkEndTime = m_time; + CheckEndMission(TRUE); + } + + if ( m_winDelay > 0.0f && !m_bEditLock ) + { + m_winDelay -= event.rTime; + if ( m_winDelay <= 0.0f ) + { + if ( m_bMovieLock ) + { + m_winDelay = 1.0f; + } + else + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_WIN); + m_event->AddEvent(newEvent); + } + } + } + + if ( m_lostDelay > 0.0f && !m_bEditLock ) + { + m_lostDelay -= event.rTime; + if ( m_lostDelay <= 0.0f ) + { + if ( m_bMovieLock ) + { + m_winDelay = 1.0f; + } + else + { + Event newEvent; + m_event->MakeEvent(newEvent, EVENT_LOST); + m_event->AddEvent(newEvent); + } + } + } + } + + if ( m_delayWriteMessage > 0 ) + { + m_delayWriteMessage --; + if ( m_delayWriteMessage == 0 ) + { + m_displayText->DisplayError(INFO_WRITEOK, D3DVECTOR(0.0f,0.0f,0.0f)); + } + } + + return S_OK; +} + +// Makes the event for all robots. + +BOOL CRobotMain::EventObject(const Event &event) +{ + CObject* pObj; + int i; + + if ( m_bFreePhoto ) return S_OK; + + m_bResetCreate = FALSE; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + pObj->EventProcess(event); + } + + if ( m_bResetCreate ) + { + ResetCreate(); + } + + return S_OK; +} + + +// Calculates the point of arrival of the camera. + +D3DVECTOR CRobotMain::LookatPoint(D3DVECTOR eye, float angleH, float angleV, + float length) +{ + D3DVECTOR lookat; + + lookat = eye; + lookat.z += length; + + RotatePoint(eye, angleH, angleV, lookat); + return lookat; +} + + + +char* SkipNum(char *p) +{ + while ( *p == ' ' || *p == '.' || *p == '-' || (*p >= '0' && *p <= '9') ) + { + p++; + } + return p; +} + +// Conversion of units. + +void CRobotMain::Convert() +{ + FILE* file = NULL; + FILE* fileNew = NULL; + char line[500]; + char lineNew[500]; + char s[200]; + char* base; + char* p; + int rank; + D3DVECTOR pos; + float value; + + base = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + + m_dialog->BuildSceneName(line, base, rank); + file = fopen(line, "r"); + if ( file == NULL ) return; + + strcpy(line+strlen(line)-4, ".new"); + fileNew = fopen(line, "w"); + if ( fileNew == NULL ) return; + + while ( fgets(line, 500, file) != NULL ) + { + strcpy(lineNew, line); + + if ( Cmd(line, "DeepView") ) + { + p = strstr(line, "air="); + if ( p != 0 ) + { + value = OpFloat(line, "air", 500.0f); + value /= g_unit; + p[0] = 0; + p = SkipNum(p+4); + strcpy(lineNew, line); + strcat(lineNew, "air="); + sprintf(s, "%.2f", value); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + + p = strstr(line, "water="); + if ( p != 0 ) + { + value = OpFloat(line, "water", 100.0f); + value /= g_unit; + p[0] = 0; + p = SkipNum(p+6); + strcpy(lineNew, line); + strcat(lineNew, "water="); + sprintf(s, "%.2f", value); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + } + + if ( Cmd(line, "TerrainGenerate") ) + { + p = strstr(line, "vision="); + if ( p != 0 ) + { + value = OpFloat(line, "vision", 500.0f); + value /= g_unit; + p[0] = 0; + p = SkipNum(p+7); + strcpy(lineNew, line); + strcat(lineNew, "vision="); + sprintf(s, "%.2f", value); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + } + + if ( Cmd(line, "CreateObject") || + Cmd(line, "CreateSpot") ) + { + p = strstr(line, "pos="); + if ( p != 0 ) + { + pos = OpPos(line, "pos"); + pos.x /= g_unit; + pos.y /= g_unit; + pos.z /= g_unit; + p[0] = 0; + p = SkipNum(p+4); + p = SkipNum(p+1); + strcpy(lineNew, line); + strcat(lineNew, "pos="); + sprintf(s, "%.2f", pos.x); + strcat(lineNew, s); + strcat(lineNew, ";"); + sprintf(s, "%.2f", pos.z); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + } + + if ( Cmd(line, "EndMissionTake") ) + { + p = strstr(line, "pos="); + if ( p != 0 ) + { + pos = OpPos(line, "pos"); + pos.x /= g_unit; + pos.y /= g_unit; + pos.z /= g_unit; + p[0] = 0; + p = SkipNum(p+4); + p = SkipNum(p+1); + strcpy(lineNew, line); + strcat(lineNew, "pos="); + sprintf(s, "%.2f", pos.x); + strcat(lineNew, s); + strcat(lineNew, ";"); + sprintf(s, "%.2f", pos.z); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + + p = strstr(line, "dist="); + if ( p != 0 ) + { + value = OpFloat(line, "dist", 32.0f); + value /= g_unit; + p[0] = 0; + p = SkipNum(p+5); + strcpy(lineNew, line); + strcat(lineNew, "dist="); + sprintf(s, "%.2f", value); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + } + + if ( Cmd(line, "Camera") ) + { + p = strstr(line, "pos="); + if ( p != 0 ) + { + pos = OpPos(line, "pos"); + pos.x /= g_unit; + pos.y /= g_unit; + pos.z /= g_unit; + p[0] = 0; + p = SkipNum(p+4); + p = SkipNum(p+1); + strcpy(lineNew, line); + strcat(lineNew, "pos="); + sprintf(s, "%.2f", pos.x); + strcat(lineNew, s); + strcat(lineNew, ";"); + sprintf(s, "%.2f", pos.z); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + + p = strstr(line, "h="); + if ( p != 0 ) + { + value = OpFloat(line, "h", 32.0f); + value /= g_unit; + p[0] = 0; + p = SkipNum(p+2); + strcpy(lineNew, line); + strcat(lineNew, "h="); + sprintf(s, "%.2f", value); + strcat(lineNew, s); + strcat(lineNew, " "); + strcat(lineNew, p); + } + strcpy(line, lineNew); + } + + fputs(lineNew, fileNew); + } + + fclose(fileNew); + fclose(file); +} + +// Load the scene for the character. + +void CRobotMain::ScenePerso() +{ + CObject* pObj; + + DeleteAllObjects(); // removes all the current 3D Scene + m_engine->FlushObject(); + m_terrain->FlushRelief(); // all flat + m_terrain->FlushBuildingLevel(); + m_terrain->FlushFlyingLimit(); + m_light->FlushLight(); + m_particule->FlushParticule(); + m_iMan->Flush(CLASS_OBJECT); + m_iMan->Flush(CLASS_PHYSICS); + m_iMan->Flush(CLASS_BRAIN); + m_iMan->Flush(CLASS_PYRO); + + m_dialog->SetSceneName("perso"); + m_dialog->SetSceneRank(0); + CreateScene(FALSE, TRUE, FALSE); // sets scene + + m_engine->SetDrawWorld(FALSE); // does not draw anything on the interface + m_engine->SetDrawFront(TRUE); // draws on the human interface + pObj = SearchHuman(); + if ( pObj != 0 ) + { + CMotionHuman* mh; + + pObj->SetDrawFront(TRUE); // draws the interface + + mh = (CMotionHuman*)pObj->RetMotion(); + if ( mh != 0 ) + { + mh->StartDisplayPerso(); + } + } +} + +// Creates the whole stage. + +void CRobotMain::CreateScene(BOOL bSoluce, BOOL bFixScene, BOOL bResetObject) +{ + CObject* pObj; + CObject* pSel; + CMotion* motion; + FILE* file = NULL; + char line[500]; + char name[200]; + char dir[100]; + char op[100]; + char* read; + char* stack; + char* base; + D3DCOLORVALUE color; + D3DVECTOR pos; + int rank, obj, i, rankObj, rankGadget; + +//? Convert(); + + base = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + read = m_dialog->RetSceneRead(); + stack = m_dialog->RetStackRead(); + m_dialog->SetUserDir(base, rank); + + m_bFixScene = bFixScene; + + g_id = 0; + m_bBase = FALSE; + + if ( !bResetObject ) + { + g_build = 0; + g_researchDone = 0; // no research done + g_researchEnable = 0; + + FlushDisplayInfo(); + m_terrain->LevelFlush(); + m_audioTrack = 0; + m_bAudioRepeat = TRUE; + m_displayText->SetDelay(1.0f); + m_displayText->SetEnable(TRUE); + m_bImmediatSatCom = FALSE; + m_endingWinRank = 0; + m_endingLostRank = 0; + m_endTakeTotal = 0; + m_endTakeResearch = 0; + m_endTakeWinDelay = 2.0f; + m_endTakeLostDelay = 2.0f; + m_obligatoryTotal = 0; + m_prohibitedTotal = 0; + m_bMapShow = TRUE; + m_bMapImage = FALSE; + m_mapFilename[0] = 0; + + m_colorRefBot.r = 10.0f/256.0f; + m_colorRefBot.g = 166.0f/256.0f; + m_colorRefBot.b = 254.0f/256.0f; // blue + m_colorRefBot.a = 0.0f; + m_colorNewBot = m_colorRefBot; + + m_colorRefAlien.r = 135.0f/256.0f; + m_colorRefAlien.g = 170.0f/256.0f; + m_colorRefAlien.b = 13.0f/256.0f; // green + m_colorRefAlien.a = 0.0f; + m_colorNewAlien = m_colorRefAlien; + + m_colorRefGreen.r = 135.0f/256.0f; + m_colorRefGreen.g = 170.0f/256.0f; + m_colorRefGreen.b = 13.0f/256.0f; // green + m_colorRefGreen.a = 0.0f; + m_colorNewGreen = m_colorRefGreen; + + m_colorRefWater.r = 25.0f/256.0f; + m_colorRefWater.g = 255.0f/256.0f; + m_colorRefWater.b = 240.0f/256.0f; // cyan + m_colorRefWater.a = 0.0f; + m_colorNewWater = m_colorRefWater; + + m_dialog->BuildResumeName(m_title, base, rank); + m_dialog->BuildResumeName(m_resume, base, rank); + GetResource(RES_TEXT, RT_SCRIPT_NEW, m_scriptName); + m_scriptFile[0] = 0; + } + + m_dialog->BuildSceneName(line, base, rank); + file = fopen(line, "r"); + if ( file == NULL ) return; + + rankObj = 0; + rankGadget = 0; + pSel = 0; + + while ( fgets(line, 500, file) != NULL ) + { + for ( i=0 ; i<500 ; i++ ) + { + if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space + if ( line[i] == '/' && line[i+1] == '/' ) + { + line[i] = 0; + break; + } + } + + sprintf(op, "Title.%c", RetLanguageLetter()); + if ( Cmd(line, op) && !bResetObject ) + { + OpString(line, "text", m_title); + } + + sprintf(op, "Resume.%c", RetLanguageLetter()); + if ( Cmd(line, op) && !bResetObject ) + { + OpString(line, "text", m_resume); + } + + sprintf(op, "ScriptName.%c", RetLanguageLetter()); + if ( Cmd(line, op) && !bResetObject ) + { + OpString(line, "text", m_scriptName); + } + + if ( Cmd(line, "ScriptFile") && !bResetObject ) + { + OpString(line, "name", m_scriptFile); + } + + if ( Cmd(line, "Instructions") && !bResetObject ) + { + OpString(line, "name", name); +//? sprintf(m_infoFilename[SATCOM_HUSTON], "help\\%s", name); + UserDir(m_infoFilename[SATCOM_HUSTON], name, "help"); + + m_bImmediatSatCom = OpInt(line, "immediat", 0); + } + + if ( Cmd(line, "Satellite") && !bResetObject ) + { + OpString(line, "name", name); +//? sprintf(m_infoFilename[SATCOM_SAT], "help\\%s", name); + UserDir(m_infoFilename[SATCOM_SAT], name, "help"); + } + + if ( Cmd(line, "Loading") && !bResetObject ) + { + OpString(line, "name", name); +//? sprintf(m_infoFilename[SATCOM_LOADING], "help\\%s", name); + UserDir(m_infoFilename[SATCOM_LOADING], name, "help"); + } + + if ( Cmd(line, "HelpFile") && !bResetObject ) + { + OpString(line, "name", name); +//? sprintf(m_infoFilename[SATCOM_PROG], "help\\%s", name); + UserDir(m_infoFilename[SATCOM_PROG], name, "help"); + } + if ( Cmd(line, "SoluceFile") && !bResetObject ) + { + OpString(line, "name", name); +//? sprintf(m_infoFilename[SATCOM_SOLUCE], "help\\%s", name); + UserDir(m_infoFilename[SATCOM_SOLUCE], name, "help"); + } + + if ( Cmd(line, "EndingFile") && !bResetObject ) + { + m_endingWinRank = OpInt(line, "win", 0); + m_endingLostRank = OpInt(line, "lost", 0); + } + + if ( Cmd(line, "MessageDelay") && !bResetObject ) + { + m_displayText->SetDelay(OpFloat(line, "factor", 1.0f)); + } + + if ( Cmd(line, "Audio") && !bResetObject ) + { + m_audioTrack = OpInt(line, "track", 0); + m_bAudioRepeat = OpInt(line, "repeat", 1); + } + + if ( Cmd(line, "AmbiantColor") && !bResetObject ) + { + m_engine->SetAmbiantColor(OpColor(line, "air", 0x88888888), 0); + m_engine->SetAmbiantColor(OpColor(line, "water", 0x88888888), 1); + } + + if ( Cmd(line, "FogColor") && !bResetObject ) + { + m_engine->SetFogColor(OpColor(line, "air", 0x88888888), 0); + m_engine->SetFogColor(OpColor(line, "water", 0x88888888), 1); + } + + if ( Cmd(line, "VehicleColor") && !bResetObject ) + { + m_colorNewBot = RetColor(OpColor(line, "color", 0x88888888)); + } + + if ( Cmd(line, "InsectColor") && !bResetObject ) + { + m_colorNewAlien = RetColor(OpColor(line, "color", 0x88888888)); + } + + if ( Cmd(line, "GreeneryColor") && !bResetObject ) + { + m_colorNewGreen = RetColor(OpColor(line, "color", 0x88888888)); + } + + if ( Cmd(line, "DeepView") && !bResetObject ) + { + m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, TRUE); + m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, TRUE); + } + + if ( Cmd(line, "FogStart") && !bResetObject ) + { + m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0); + m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1); + } + + if ( Cmd(line, "SecondTexture") && !bResetObject ) + { + m_engine->SetSecondTexture(OpInt(line, "rank", 1)); + } + + if ( Cmd(line, "Background") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, ""); + m_engine->SetBackground(dir, + OpColor(line, "up", 0x00000000), + OpColor(line, "down", 0x00000000), + OpColor(line, "cloudUp", 0x00000000), + OpColor(line, "cloudDown", 0x00000000), + OpInt(line, "full", 0)); + } + + if ( Cmd(line, "Planet") && !bResetObject ) + { + D3DVECTOR ppos, uv1, uv2; + + ppos = OpPos(line, "pos"); + uv1 = OpPos(line, "uv1"); + uv2 = OpPos(line, "uv2"); + OpString(line, "image", name); + UserDir(dir, name, ""); + m_planet->Create(OpInt(line, "mode", 0), + FPOINT(ppos.x, ppos.z), + OpFloat(line, "dim", 0.2f), + OpFloat(line, "speed", 0.0f), + OpFloat(line, "dir", 0.0f), + dir, + FPOINT(uv1.x, uv1.z), + FPOINT(uv2.x, uv2.z)); + } + + if ( Cmd(line, "FrontsizeName") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, ""); + m_engine->SetFrontsizeName(dir); + } + + if ( Cmd(line, "Global") && !bResetObject ) + { + g_unit = OpFloat(line, "unitScale", 4.0f); + m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f)); + m_bShortCut = OpInt(line, "shortcut", 1); + } + + if ( Cmd(line, "TerrainGenerate") && !bResetObject ) + { + m_terrain->Generate(OpInt(line, "mosaic", 20), + OpInt(line, "brick", 3), + OpFloat(line, "size", 20.0f), + OpFloat(line, "vision", 500.0f)*UNIT, + OpInt(line, "depth", 2), + OpFloat(line, "hard", 0.5f)); + } + + if ( Cmd(line, "TerrainWind") && !bResetObject ) + { + m_terrain->SetWind(OpPos(line, "speed")); + } + + if ( Cmd(line, "TerrainRelief") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, "textures"); + m_terrain->ReliefFromBMP(dir, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1)); + } + + if ( Cmd(line, "TerrainReliefDXF") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, "textures"); + m_terrain->ReliefFromDXF(dir, OpFloat(line, "factor", 1.0f)); + } + + if ( Cmd(line, "TerrainResource") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, "textures"); + m_terrain->ResFromBMP(dir); + } + + if ( Cmd(line, "TerrainWater") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, ""); + pos.x = OpFloat(line, "moveX", 0.0f); + pos.y = OpFloat(line, "moveY", 0.0f); + pos.z = pos.x; + m_water->Create(OpTypeWater(line, "air", WATER_TT), + OpTypeWater(line, "water", WATER_TT), + dir, + RetColor(OpColor(line, "diffuse", 0xffffffff)), + RetColor(OpColor(line, "ambiant", 0xffffffff)), + OpFloat(line, "level", 100.0f)*UNIT, + OpFloat(line, "glint", 1.0f), + pos); + m_colorNewWater = RetColor(OpColor(line, "color", RetColor(m_colorRefWater))); + m_colorShiftWater = OpFloat(line, "brightness", 0.0f); + } + + if ( Cmd(line, "TerrainLava") && !bResetObject ) + { + m_water->SetLava(OpInt(line, "mode", 0)); + } + + if ( Cmd(line, "TerrainCloud") && !bResetObject ) + { + OpString(line, "image", name); + UserDir(dir, name, ""); + m_cloud->Create(dir, + RetColor(OpColor(line, "diffuse", 0xffffffff)), + RetColor(OpColor(line, "ambiant", 0xffffffff)), + OpFloat(line, "level", 500.0f)*UNIT); + } + + if ( Cmd(line, "TerrainBlitz") && !bResetObject ) + { + m_blitz->Create(OpFloat(line, "sleep", 0.0f), + OpFloat(line, "delay", 3.0f), + OpFloat(line, "magnetic", 50.0f)*UNIT); + } + + if ( Cmd(line, "TerrainInitTextures") && !bResetObject ) + { + int dx, dy, tt[100]; + char* op; + + OpString(line, "image", name); + AddExt(name, ".tga"); + dx = OpInt(line, "dx", 1); + dy = OpInt(line, "dy", 1); + op = SearchOp(line, "table"); + for ( i=0 ; iInitTextures(name, tt, dx, dy); + } + + if ( Cmd(line, "TerrainInit") && !bResetObject ) + { + m_terrain->LevelInit(OpInt(line, "id", 1)); + } + + if ( Cmd(line, "TerrainMaterial") && !bResetObject ) + { + OpString(line, "image", name); + AddExt(name, ".tga"); + if ( strstr(name, "%user%") != 0 ) + { + CopyFileToTemp(name); + } + + m_terrain->LevelMaterial(OpInt(line, "id", 0), + name, + OpFloat(line, "u", 0.0f), + OpFloat(line, "v", 0.0f), + OpInt(line, "up", 1), + OpInt(line, "right", 1), + OpInt(line, "down", 1), + OpInt(line, "left", 1), + OpFloat(line, "hard", 0.5f)); + } + + if ( Cmd(line, "TerrainLevel") && !bResetObject ) + { + int id[50]; + char* op; + + op = SearchOp(line, "id"); + i = 0; + while ( TRUE ) + { + id[i] = GetInt(op, i, 0); + if ( id[i++] == 0 ) break; + } + + m_terrain->LevelGenerate(id, + OpFloat(line, "min", 0.0f)*UNIT, + OpFloat(line, "max", 100.0f)*UNIT, + OpFloat(line, "slope", 5.0f), + OpFloat(line, "freq", 100.0f), + OpPos(line, "center")*g_unit, + OpFloat(line, "radius", 0.0f)*g_unit); + } + + if ( Cmd(line, "TerrainCreate") && !bResetObject ) + { + m_terrain->CreateObjects(TRUE); + } + + if ( Cmd(line, "BeginObject") ) + { + InitEye(); + SetMovieLock(FALSE); + if ( !m_bFixScene ) + { +//? CreateObject(D3DVECTOR(0.0f, 0.0f, 0.0f), 0.0f, 0.0f, OBJECT_TOTO); + } + + if ( read[0] != 0 ) // loading file ? + { + pSel = IOReadScene(read, stack); + } + } + + if ( Cmd(line, "CreateObject") && read[0] == 0 ) + { + CObject* pObj; + CBrain* pBrain; + CAuto* pAuto; + CPyro* pyro; + ObjectType type; + PyroType pType; + CameraType cType; + Info info; + float dir; + char op[20]; + char text[100]; + char* p; + int run, gadget; + + type = OpTypeObject(line, "type", OBJECT_NULL); + + gadget = OpInt(line, "gadget", -1); + if ( gadget == -1 ) + { + gadget = 0; + if ( type == OBJECT_TECH || + (type >= OBJECT_PLANT0 && + type <= OBJECT_PLANT19 ) || + (type >= OBJECT_TREE0 && + type <= OBJECT_TREE9 ) || + (type >= OBJECT_TEEN0 && + type <= OBJECT_TEEN49 ) || + (type >= OBJECT_QUARTZ0 && + type <= OBJECT_QUARTZ9 ) || + (type >= OBJECT_ROOT0 && + type <= OBJECT_ROOT4 ) ) // not ROOT5! + { + if ( type != OBJECT_TEEN11 && // lamp? + type != OBJECT_TEEN12 && // coke? + type != OBJECT_TEEN20 && // wall? + type != OBJECT_TEEN21 && // wall? + type != OBJECT_TEEN22 && // wall? + type != OBJECT_TEEN26 && // lamp? + type != OBJECT_TEEN28 && // bottle? + type != OBJECT_TEEN34 ) // stone? + { + gadget = 1; + } + } + } + if ( gadget != 0 ) // is this a gadget? + { + if ( !TestGadgetQuantity(rankGadget++) ) continue; + } + + pos = OpPos(line, "pos")*g_unit; + dir = OpFloat(line, "dir", 0.0f)*PI; + pObj = CreateObject(pos, dir, + OpFloat(line, "z", 1.0f), + OpFloat(line, "h", 0.0f), + type, + OpFloat(line, "power", 1.0f), + OpInt(line, "trainer", 0), + OpInt(line, "toy", 0), + OpInt(line, "option", 0)); + + if ( pObj != 0 ) + { + pObj->SetDefRank(rankObj); + + if ( type == OBJECT_BASE ) m_bBase = TRUE; + + cType = OpCamera(line, "camera"); + if ( cType != CAMERA_NULL ) + { + pObj->SetCameraType(cType); + } + pObj->SetCameraDist(OpFloat(line, "cameraDist", 50.0f)); + pObj->SetCameraLock(OpInt(line, "cameraLock", 0)); + + pType = OpPyro(line, "pyro"); + if ( pType != PT_NULL ) + { + pyro = new CPyro(m_iMan); + pyro->Create(pType, pObj); + } + + // Puts information in terminal (OBJECT_INFO). + for ( i=0 ; iSearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj->RetTruck() != 0 ) continue; + + brain = pObj->RetBrain(); + if ( brain == 0 ) continue; + + for ( j=0 ; j<10 ; j++ ) + { + if ( brain->RetCompile(j) ) continue; + + name = brain->RetScriptName(j); + if ( name[0] != 0 ) + { + brain->ReadProgram(j, name); + if ( !brain->RetCompile(j) ) nbError++; + } + } + + LoadOneScript(pObj, nbError); + } + } + while ( nbError > 0 && nbError != lastError ); + + // Load all solutions. + if ( bSoluce ) + { + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj->RetTruck() != 0 ) continue; + + brain = pObj->RetBrain(); + if ( brain == 0 ) continue; + + name = brain->RetSoluceName(); + if ( name[0] != 0 ) + { + brain->ReadSoluce(name); // load solution + } + } + } + + // Start all programs according to the command "run". + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj->RetTruck() != 0 ) continue; + + brain = pObj->RetBrain(); + if ( brain == 0 ) continue; + + run = brain->RetScriptRun(); + if ( run != -1 ) + { + brain->RunProgram(run); // starts the program + } + } +} + +// Load all programs of the robot. + +void CRobotMain::LoadOneScript(CObject *pObj, int &nbError) +{ + ObjectType type; + CBrain* brain; + char filename[_MAX_FNAME]; + char* name; + int rank, i, objRank; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return; + + if ( !IsSelectable(pObj) ) return; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return; + + objRank = pObj->RetDefRank(); + if ( objRank == -1 ) return; + + name = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + + for ( i=0 ; iRetCompile(i) ) continue; +//? if ( brain->ProgramExist(i) ) continue; + + sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt", + RetSavegameDir(), m_gamerName, name[0], rank, objRank, i); + brain->ReadProgram(i, filename); + if ( !brain->RetCompile(i) ) nbError++; + } +} + +// Load all programs of the robot. + +void CRobotMain::LoadFileScript(CObject *pObj, char* filename, int objRank, + int &nbError) +{ + ObjectType type; + CBrain* brain; + char fn[_MAX_FNAME]; + char* ldir; + char* name; + int rank, i; + + if ( objRank == -1 ) return; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return; + + name = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + + strcpy(fn, filename); + ldir = SearchLastDir(fn); + if ( ldir == 0 ) return; + + for ( i=0 ; iRetCompile(i) ) continue; +//? if ( brain->ProgramExist(i) ) continue; + + sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i); + brain->ReadProgram(i, fn); + if ( !brain->RetCompile(i) ) nbError++; + } +} + +// Saves all programs of all the robots. + +void CRobotMain::SaveAllScript() +{ + CObject* pObj; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + SaveOneScript(pObj); + } +} + +// Saves all programs of the robot. +// If a program does not exist, the corresponding file is destroyed. + +void CRobotMain::SaveOneScript(CObject *pObj) +{ + ObjectType type; + CBrain* brain; + char filename[_MAX_FNAME]; + char* name; + int rank, i, objRank; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return; + + if ( !IsSelectable(pObj) ) return; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return; + + objRank = pObj->RetDefRank(); + if ( objRank == -1 ) return; + + name = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + + for ( i=0 ; iWriteProgram(i, filename); + } +} + +// Saves all programs of the robot. +// If a program does not exist, the corresponding file is destroyed. + +void CRobotMain::SaveFileScript(CObject *pObj, char* filename, int objRank) +{ + ObjectType type; + CBrain* brain; + char fn[_MAX_FNAME]; + char* ldir; + char* name; + int rank, i; + + if ( objRank == -1 ) return; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return; + + name = m_dialog->RetSceneName(); + rank = m_dialog->RetSceneRank(); + + strcpy(fn, filename); + ldir = SearchLastDir(fn); + if ( ldir == 0 ) return; + + for ( i=0 ; iWriteProgram(i, fn); + } +} + +// Saves the stack of the program in execution of a robot. + +BOOL CRobotMain::SaveFileStack(CObject *pObj, FILE *file, int objRank) +{ + ObjectType type; + CBrain* brain; + + if ( objRank == -1 ) return TRUE; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return TRUE; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return TRUE; + + return brain->WriteStack(file); +} + +// Resumes the execution stack of the program in a robot. + +BOOL CRobotMain::ReadFileStack(CObject *pObj, FILE *file, int objRank) +{ + ObjectType type; + CBrain* brain; + + if ( objRank == -1 ) return TRUE; + + brain = pObj->RetBrain(); + if ( brain == 0 ) return TRUE; + + type = pObj->RetType(); + if ( type == OBJECT_HUMAN ) return TRUE; + + return brain->ReadStack(file); +} + + +// Empty the list. + +BOOL CRobotMain::FlushNewScriptName() +{ + int i; + + for ( i=0 ; i 0 ) return TRUE; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + pBrain = pObj->RetBrain(); + if ( pBrain != 0 ) + { + if ( pBrain->IsBusy() ) return TRUE; + } + +//? pAuto = pObj->RetAuto(); +//? if ( pAuto != 0 ) +//? { +//? if ( pAuto->RetBusy() ) return TRUE; +//? } + } + return FALSE; +} + +// Writes an object into the backup file. + +void CRobotMain::IOWriteObject(FILE *file, CObject* pObj, char *cmd) +{ + D3DVECTOR pos; + CBrain* pBrain; + char line[3000]; + char name[100]; + int run, i; + + if ( pObj->RetType() == OBJECT_FIX ) return; + + strcpy(line, cmd); + + sprintf(name, " type=%s", GetTypeObject(pObj->RetType())); + strcat(line, name); + + sprintf(name, " id=%d", pObj->RetID()); + strcat(line, name); + + pos = pObj->RetPosition(0)/g_unit; + sprintf(name, " pos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z); + strcat(line, name); + + pos = pObj->RetAngle(0)/(PI/180.0f); + sprintf(name, " angle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z); + strcat(line, name); + + pos = pObj->RetZoom(0); + sprintf(name, " zoom=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z); + strcat(line, name); + + for ( i=1 ; iRetObjectRank(i) == -1 ) continue; + + pos = pObj->RetPosition(i); + if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f ) + { + pos /= g_unit; + sprintf(name, " p%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z); + strcat(line, name); + } + + pos = pObj->RetAngle(i); + if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f ) + { + pos /= (PI/180.0f); + sprintf(name, " a%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z); + strcat(line, name); + } + + pos = pObj->RetZoom(i); + if ( pos.x != 1.0f || pos.y != 1.0f || pos.z != 1.0f ) + { + sprintf(name, " z%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z); + strcat(line, name); + } + } + + sprintf(name, " trainer=%d", pObj->RetTrainer()); + strcat(line, name); + + sprintf(name, " option=%d", pObj->RetOption()); + strcat(line, name); + + if ( pObj == m_infoObject ) // selects object? + { + sprintf(name, " select=1"); + strcat(line, name); + } + + pObj->Write(line); + + if ( pObj->RetType() == OBJECT_BASE ) + { + sprintf(name, " run=3"); // stops and open (PARAM_FIXSCENE) + strcat(line, name); + } + + pBrain = pObj->RetBrain(); + if ( pBrain != 0 ) + { + run = pBrain->RetProgram(); + if ( run != -1 ) + { + sprintf(name, " run=%d", run+1); + strcat(line, name); + } + } + + strcat(line, "\n"); + fputs(line, file); +} + +// Saves the current game. + +BOOL CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info) +{ + FILE* file; + char line[500]; + char* name; + CObject *pObj, *pPower, *pFret; + float sleep, delay, magnetic, progress; + int i, objRank; + long version; + + file = fopen(filename, "w"); + if ( file == NULL ) return FALSE; + + sprintf(line, "Title text=\"%s\"\n", info); + fputs(line, file); + + sprintf(line, "Version maj=%d min=%d\n", 0, 1); + fputs(line, file); + + name = m_dialog->RetSceneName(); + if ( strcmp(name, "user") == 0 ) + { + sprintf(line, "Mission base=\"%s\" rank=%.3d dir=\"%s\"\n", name, m_dialog->RetSceneRank(), m_dialog->RetSceneDir()); + } + else + { + sprintf(line, "Mission base=\"%s\" rank=%.3d\n", name, m_dialog->RetSceneRank()); + } + fputs(line, file); + + sprintf(line, "Map zoom=%.2f\n", m_map->RetZoomMap()); + fputs(line, file); + + sprintf(line, "DoneResearch bits=%d\n", g_researchDone); + fputs(line, file); + + if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) ) + { + sprintf(line, "BlitzMode sleep=%.2f delay=%.2f magnetic=%.2f progress=%.2f\n", sleep, delay, magnetic/g_unit, progress); + fputs(line, file); + } + + objRank = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetType() == OBJECT_TOTO ) continue; + if ( pObj->RetType() == OBJECT_FIX ) continue; + if ( pObj->RetTruck() != 0 ) continue; + if ( pObj->RetBurn() ) continue; + if ( pObj->RetDead() ) continue; + if ( pObj->RetExplo() ) continue; + + pPower = pObj->RetPower(); + pFret = pObj->RetFret(); + + if ( pFret != 0 ) // object transported? + { + IOWriteObject(file, pFret, "CreateFret"); + } + + if ( pPower != 0 ) // battery transported? + { + IOWriteObject(file, pPower, "CreatePower"); + } + + IOWriteObject(file, pObj, "CreateObject"); + + SaveFileScript(pObj, filename, objRank++); + } + fclose(file); + +#if CBOT_STACK + // Writes the file of stacks of execution. + file = fOpen(filecbot, "wb"); + if ( file == NULL ) return FALSE; + + version = 1; + fWrite(&version, sizeof(long), 1, file); // version of COLOBOT + version = CBotProgram::GivVersion(); + fWrite(&version, sizeof(long), 1, file); // version of CBOT + + objRank = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetType() == OBJECT_TOTO ) continue; + if ( pObj->RetType() == OBJECT_FIX ) continue; + if ( pObj->RetTruck() != 0 ) continue; + if ( pObj->RetBurn() ) continue; + if ( pObj->RetDead() ) continue; + + if ( !SaveFileStack(pObj, file, objRank++) ) break; + } + CBotClass::SaveStaticState(file); + fClose(file); +#endif + + m_delayWriteMessage = 4; // displays message in 3 frames + return TRUE; +} + +// Resumes the game. + +CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank) +{ + CObject* pObj; +//? CBrain* pBrain; + CAuto* pAuto; + D3DVECTOR pos, dir, zoom; + ObjectType type; + int id, run, trainer, toy, option, i; + char op[10]; + + pos = OpDir(line, "pos")*g_unit; + dir = OpDir(line, "angle")*(PI/180.0f); + zoom = OpDir(line, "zoom"); + type = OpTypeObject(line, "type", OBJECT_NULL); + id = OpInt(line, "id", 0); + if ( type == OBJECT_NULL ) return 0; + trainer = OpInt(line, "trainer", 0); + toy = OpInt(line, "toy", 0); + option = OpInt(line, "option", 0); + pObj = CreateObject(pos, dir.y, 1.0f, 0.0f, type, 0.0f, trainer, toy, option); + pObj->SetDefRank(objRank); + pObj->SetPosition(0, pos); + pObj->SetAngle(0, dir); + pObj->SetID(id); + if ( g_id < id ) g_id = id; + + if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f ) + { + pObj->SetZoom(0, zoom); + } + + for ( i=1 ; iRetObjectRank(i) == -1 ) continue; + + sprintf(op, "p%d", i); + pos = OpDir(line, op); + if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f ) + { + pObj->SetPosition(i, pos*g_unit); + } + + sprintf(op, "a%d", i); + dir = OpDir(line, op); + if ( dir.x != 0.0f || dir.y != 0.0f || dir.z != 0.0f ) + { + pObj->SetAngle(i, dir*(PI/180.0f)); + } + + sprintf(op, "z%d", i); + zoom = OpDir(line, op); + if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f ) + { + pObj->SetZoom(i, zoom); + } + } + + if ( type == OBJECT_BASE ) m_bBase = TRUE; + + pObj->Read(line); + +#if CBOT_STACK +#else + LoadFileScript(pObj, filename, objRank, i); +#endif + + run = OpInt(line, "run", -1); + if ( run != -1 ) + { +#if CBOT_STACK +#else + pBrain = pObj->RetBrain(); + if ( pBrain != 0 ) + { + pBrain->RunProgram(run-1); // starts the program + } +#endif + + pAuto = pObj->RetAuto(); + if ( pAuto != 0 ) + { + pAuto->Start(run); // starts the film + } + } + + return pObj; +} + +// Resumes some part of the game. + +CObject* CRobotMain::IOReadScene(char *filename, char *filecbot) +{ + FILE* file; + CObject *pObj, *pPower, *pFret, *pSel; + char line[3000]; + float sleep, delay, progress, magnetic; + int i, objRank, nbError, lastError; + long version; + + m_bBase = FALSE; + + file = fopen(filename, "r"); + if ( file == NULL ) return 0; + + pFret = 0; + pPower = 0; + pSel = 0; + objRank = 0; + while ( fgets(line, 3000, file) != NULL ) + { + for ( i=0 ; i<3000 ; i++ ) + { + if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space + if ( line[i] == '/' && line[i+1] == '/' ) + { + line[i] = 0; + break; + } + } + + if ( Cmd(line, "Map") ) + { + m_map->ZoomMap(OpFloat(line, "zoom", 1.0f)); + } + + if ( Cmd(line, "DoneResearch") ) + { + g_researchDone = OpInt(line, "bits", 0); + } + + if ( Cmd(line, "BlitzMode") ) + { + sleep = OpFloat(line, "sleep", 0.0f); + delay = OpFloat(line, "delay", 3.0f); + magnetic = OpFloat(line, "magnetic", 50.0f)*g_unit; + progress = OpFloat(line, "progress", 0.0f); + m_blitz->SetStatus(sleep, delay, magnetic, progress); + } + + if ( Cmd(line, "CreateFret") ) + { + pFret = IOReadObject(line, filename, -1); + } + + if ( Cmd(line, "CreatePower") ) + { + pPower = IOReadObject(line, filename, -1); + } + + if ( Cmd(line, "CreateObject") ) + { + pObj = IOReadObject(line, filename, objRank++); + + if ( OpInt(line, "select", 0) ) + { + pSel = pObj; + } + + if ( pFret != 0 ) + { + CTaskManip* task; + + pObj->SetFret(pFret); + task = new CTaskManip(m_iMan, pObj); + task->Start(TMO_AUTO, TMA_GRAB); // holds the object! + delete task; + } + + if ( pPower != 0 ) + { + pObj->SetPower(pPower); + pPower->SetTruck(pObj); + } + + pFret = 0; + pPower = 0; + } + } + fclose(file); + +#if CBOT_STACK + // Compiles scripts. + nbError = 0; + do + { + lastError = nbError; + nbError = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj->RetTruck() != 0 ) continue; + + objRank = pObj->RetDefRank(); + if ( objRank == -1 ) continue; + + LoadFileScript(pObj, filename, objRank, nbError); + } + } + while ( nbError > 0 && nbError != lastError ); + + // Reads the file of stacks of execution. + file = fOpen(filecbot, "rb"); + if ( file != NULL ) + { + fRead(&version, sizeof(long), 1, file); // version of COLOBOT + if ( version == 1 ) + { + fRead(&version, sizeof(long), 1, file); // version of CBOT + if ( version == CBotProgram::GivVersion() ) + { + objRank = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetType() == OBJECT_TOTO ) continue; + if ( pObj->RetType() == OBJECT_FIX ) continue; + if ( pObj->RetTruck() != 0 ) continue; + if ( pObj->RetBurn() ) continue; + if ( pObj->RetDead() ) continue; + + if ( !ReadFileStack(pObj, file, objRank++) ) break; + } + } + } + CBotClass::RestoreStaticState(file); + fClose(file); + } +#endif + + return pSel; +} + + +// Writes the global parameters for free play. + +void CRobotMain::WriteFreeParam() +{ + FILE* file; + char filename[_MAX_FNAME]; + char line[100]; + + m_freeResearch |= g_researchDone; + m_freeBuild |= g_build; + + if ( m_gamerName[0] == 0 ) return; + + sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName); + file = fopen(filename, "w"); + if ( file == NULL ) return; + + sprintf(line, "research=%d build=%d\n", m_freeResearch, m_freeBuild); + fputs(line, file); + fclose(file); +} + +// Reads the global parameters for free play. + +void CRobotMain::ReadFreeParam() +{ + FILE* file; + char filename[_MAX_FNAME]; + char line[100]; + + m_freeResearch = 0; + m_freeBuild = 0; + + if ( m_gamerName[0] == 0 ) return; + + sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName); + file = fopen(filename, "r"); + if ( file == NULL ) return; + + if ( fgets(line, 100, file) != NULL ) + { + sscanf(line, "research=%d build=%d\n", &m_freeResearch, &m_freeBuild); + } + + fclose(file); +} + + +// Resets all objects to their original position. + +void CRobotMain::ResetObject() +{ +#if 0 + CObject* pObj; + CObject* pTruck; + CAuto* pAuto; + CBrain* brain; + CPyro* pyro; + ResetCap cap; + D3DVECTOR pos, angle; + int i; + + // Removes all pyrotechnic effects in progress. + while ( TRUE ) + { + pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0); + if ( pyro == 0 ) break; + + pyro->DeleteObject(); + delete pyro; + } + + // Removes all bullets in progress. + m_particule->DeleteParticule(PARTIGUN1); + m_particule->DeleteParticule(PARTIGUN2); + m_particule->DeleteParticule(PARTIGUN3); + m_particule->DeleteParticule(PARTIGUN4); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + cap = pObj->RetResetCap(); + if ( cap == RESET_NONE ) continue; + + if ( cap == RESET_DELETE ) + { + pTruck = pObj->RetTruck(); + if ( pTruck != 0 ) + { + pTruck->SetFret(0); + pObj->SetTruck(0); + } + pObj->DeleteObject(); + delete pObj; + i --; + continue; + } + + pAuto = pObj->RetAuto(); + if ( pAuto != 0 ) + { + pAuto->Abort(); + } + + if ( pObj->RetEnable() ) // object still active? + { + brain = pObj->RetBrain(); + if ( brain != 0 ) + { + pos = pObj->RetResetPosition(); + angle = pObj->RetResetAngle(); + + if ( pos == pObj->RetPosition(0) && + angle == pObj->RetAngle(0) ) continue; + brain->StartTaskReset(pos, angle); + continue; + } + } + + pObj->SetEnable(TRUE); // active again + + pos = pObj->RetResetPosition(); + angle = pObj->RetResetAngle(); + + if ( pos == pObj->RetPosition(0) && + angle == pObj->RetAngle(0) ) continue; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_RESET, pObj); + + brain = pObj->RetBrain(); + if ( brain != 0 ) + { + brain->RunProgram(pObj->RetResetRun()); + } + } +#else + m_bResetCreate = TRUE; +#endif +} + +// Resets all objects to their original position. + +void CRobotMain::ResetCreate() +{ + CObject* pObj; + CPyro* pyro; + ResetCap cap; + int i; + + SaveAllScript(); + + // Removes all bullets in progress. + m_particule->DeleteParticule(PARTIGUN1); + m_particule->DeleteParticule(PARTIGUN2); + m_particule->DeleteParticule(PARTIGUN3); + m_particule->DeleteParticule(PARTIGUN4); + + DeselectAll(); // removes the control buttons + DeleteAllObjects(); // removes all the current 3D Scene + + m_particule->FlushParticule(); + m_terrain->FlushBuildingLevel(); + m_iMan->Flush(CLASS_OBJECT); + m_iMan->Flush(CLASS_PHYSICS); + m_iMan->Flush(CLASS_BRAIN); + m_iMan->Flush(CLASS_PYRO); + m_camera->SetType(CAMERA_DIALOG); + + CreateScene(m_dialog->RetSceneSoluce(), FALSE, TRUE); + + if ( !RetNiceReset() ) return; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + cap = pObj->RetResetCap(); + if ( cap == RESET_NONE ) continue; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_RESET, pObj); + } +} + +// Checks if the mission is over. + +Error CRobotMain::CheckEndMission(BOOL bFrame) +{ + CObject* pObj; + D3DVECTOR bPos, oPos; + ObjectType type; + int t, i, nb; + + for ( t=0 ; tSearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + // Do not use RetActif () because an invisible worm (underground) + // should be regarded as existing here! + if ( pObj->RetLock() ) continue; + if ( pObj->RetRuin() ) continue; + if ( !pObj->RetEnable() ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 || + type == OBJECT_SCRAP4 || + type == OBJECT_SCRAP5 ) // wastes? + { + type = OBJECT_SCRAP1; + } + if ( type != m_endTake[t].type ) continue; + + if ( pObj->RetTruck() == 0 ) + { + oPos = pObj->RetPosition(0); + } + else + { + oPos = pObj->RetTruck()->RetPosition(0); + } + oPos.y = 0.0f; + if ( Length2d(oPos, bPos) <= m_endTake[t].dist ) + { + nb ++; + } + } + + if ( nb <= m_endTake[t].lost ) + { + if ( m_endTake[t].type == OBJECT_HUMAN ) + { + if ( m_lostDelay == 0.0f ) + { + m_lostDelay = 0.1f; // lost immediately + m_winDelay = 0.0f; + } + m_displayText->SetEnable(FALSE); + return INFO_LOSTq; + } + else + { + if ( m_lostDelay == 0.0f ) + { + m_displayText->DisplayError(INFO_LOST, D3DVECTOR(0.0f,0.0f,0.0f)); + m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds + m_winDelay = 0.0f; + } + m_displayText->SetEnable(FALSE); + return INFO_LOST; + } + } + if ( nb < m_endTake[t].min || + nb > m_endTake[t].max ) + { + m_displayText->SetEnable(TRUE); + return ERR_MISSION_NOTERM; + } + if ( m_endTake[t].bImmediat ) + { + if ( m_winDelay == 0.0f ) + { + m_winDelay = m_endTakeWinDelay; // wins in x seconds + m_lostDelay = 0.0f; + } + m_displayText->SetEnable(FALSE); + return ERR_OK; // mission ended + } + } + + if ( m_endTakeResearch != 0 ) + { + if ( m_endTakeResearch != (m_endTakeResearch&g_researchDone) ) + { + m_displayText->SetEnable(TRUE); + return ERR_MISSION_NOTERM; + } + } + + if ( m_endTakeWinDelay == -1.0f ) + { + m_winDelay = 1.0f; // wins in one second + m_lostDelay = 0.0f; + m_displayText->SetEnable(FALSE); + return ERR_OK; // mission ended + } + + if ( bFrame && m_bBase ) return ERR_MISSION_NOTERM; + + if ( m_winDelay == 0.0f ) + { + m_displayText->DisplayError(INFO_WIN, D3DVECTOR(0.0f,0.0f,0.0f)); + m_winDelay = m_endTakeWinDelay; // wins in two seconds + m_lostDelay = 0.0f; + } + m_displayText->SetEnable(FALSE); + return ERR_OK; // mission ended +} + +// Checks if the mission is finished after displaying a message. + +void CRobotMain::CheckEndMessage(char *message) +{ + int t; + + for ( t=0 ; tDisplayError(INFO_WIN, D3DVECTOR(0.0f,0.0f,0.0f)); + m_winDelay = m_endTakeWinDelay; // wins in 2 seconds + m_lostDelay = 0.0f; + } + } +} + + +// Returns the number of instructions required. + +int CRobotMain::RetObligatoryToken() +{ + return m_obligatoryTotal; +} + +// Returns the name of a required instruction. + +char* CRobotMain::RetObligatoryToken(int i) +{ + return m_obligatoryToken[i]; +} + +// Checks if an instruction is part of the obligatory list. + +int CRobotMain::IsObligatoryToken(char *token) +{ + int i; + + for ( i=0 ; iRetGlint(); +} + +BOOL CRobotMain::RetSoluce4() +{ + return m_dialog->RetSoluce4(); +} + +BOOL CRobotMain::RetMovies() +{ + return m_dialog->RetMovies(); +} + +BOOL CRobotMain::RetNiceReset() +{ + return m_dialog->RetNiceReset(); +} + +BOOL CRobotMain::RetHimselfDamage() +{ + return m_dialog->RetHimselfDamage(); +} + +BOOL CRobotMain::RetShowSoluce() +{ + return m_bShowSoluce; +} + +BOOL CRobotMain::RetSceneSoluce() +{ + if ( m_infoFilename[SATCOM_SOLUCE][0] == 0 ) return FALSE; + return m_dialog->RetSceneSoluce(); +} + +BOOL CRobotMain::RetShowAll() +{ + return m_bShowAll; +} + +BOOL CRobotMain::RetCheatRadar() +{ + return m_bCheatRadar; +} + +char* CRobotMain::RetSavegameDir() +{ + return m_dialog->RetSavegameDir(); +} + +char* CRobotMain::RetPublicDir() +{ + return m_dialog->RetPublicDir(); +} + +char* CRobotMain::RetFilesDir() +{ + return m_dialog->RetFilesDir(); +} + + +// Change the player's name. + +void CRobotMain::SetGamerName(char *name) +{ + strcpy(m_gamerName, name); + SetGlobalGamerName(m_gamerName); + ReadFreeParam(); +} + +// Gives the player's name. + +char* CRobotMain::RetGamerName() +{ + return m_gamerName; +} + + +// Returns the representation to use for the player. + +int CRobotMain::RetGamerFace() +{ + return m_dialog->RetGamerFace(); +} + +// Returns the representation to use for the player. + +int CRobotMain::RetGamerGlasses() +{ + return m_dialog->RetGamerGlasses(); +} + +// Returns the mode with just the head. + +BOOL CRobotMain::RetGamerOnlyHead() +{ + return m_dialog->RetGamerOnlyHead(); +} + +// Returns the angle of presentation. + +float CRobotMain::RetPersoAngle() +{ + return m_dialog->RetPersoAngle(); +} + + +// Changes on the pause mode. + +void CRobotMain::ChangePause(BOOL bPause) +{ + m_bPause = bPause; + m_engine->SetPause(m_bPause); + + m_sound->MuteAll(m_bPause); + CreateShortcuts(); + if ( m_bPause ) HiliteClear(); +} + + +// Changes game speed + +void CRobotMain::SetSpeed(float speed) +{ + CButton* pb; + char text[10]; + + m_engine->SetSpeed(speed); + + pb = (CButton*)m_interface->SearchControl(EVENT_SPEED); + if ( pb != 0 ) + { + if ( speed == 1.0f ) + { + pb->ClearState(STATE_VISIBLE); + } + else + { + sprintf(text, "x%.1f", speed); + pb->SetName(text); + pb->SetState(STATE_VISIBLE); + } + } +} + +float CRobotMain::RetSpeed() +{ + return m_engine->RetSpeed(); +} + + +// Creates interface shortcuts to the units. + +BOOL CRobotMain::CreateShortcuts() +{ + if ( m_phase != PHASE_SIMUL ) return FALSE; + if ( !m_bShortCut ) return FALSE; + return m_short->CreateShortcuts(); +} + +// Updates the map. + +void CRobotMain::UpdateMap() +{ + m_map->UpdateMap(); +} + +// Indicates whether the mini-map is visible. + +BOOL CRobotMain::RetShowMap() +{ + return m_map->RetShowMap() && m_bMapShow; +} + + +// Management of the lock mode for movies. + +void CRobotMain::SetMovieLock(BOOL bLock) +{ + m_bMovieLock = bLock; + m_engine->SetMovieLock(m_bMovieLock); + + CreateShortcuts(); + m_map->ShowMap(!m_bMovieLock && m_bMapShow); + if ( m_bMovieLock ) HiliteClear(); + m_engine->SetMouseHide(m_bMovieLock); +} + +BOOL CRobotMain::RetMovieLock() +{ + return m_bMovieLock; +} + +BOOL CRobotMain::RetInfoLock() +{ + return ( m_displayInfo != 0 ); // info in progress? +} + +// Management of the blocking of the call of SatCom. + +void CRobotMain::SetSatComLock(BOOL bLock) +{ + m_bSatComLock = bLock; +} + +BOOL CRobotMain::RetSatComLock() +{ + return m_bSatComLock; +} + +// Management of the lock mode for the edition. + +void CRobotMain::SetEditLock(BOOL bLock, BOOL bEdit) +{ + m_bEditLock = bLock; + + CreateShortcuts(); + + // Do not remove the card if it contains a still image. + if ( !bLock || !m_map->RetFixImage() ) + { + m_map->ShowMap(!m_bEditLock && m_bMapShow); + } + + m_displayText->HideText(bLock); + m_engine->FlushPressKey(); + + if ( m_bEditLock ) + { + HiliteClear(); + } + else + { + m_bEditFull = FALSE; + } +} + +BOOL CRobotMain::RetEditLock() +{ + return m_bEditLock; +} + +// Management of the fullscreen mode during editing. + +void CRobotMain::SetEditFull(BOOL bFull) +{ + m_bEditFull = bFull; +} + +BOOL CRobotMain::RetEditFull() +{ + return m_bEditFull; +} + + +BOOL CRobotMain::RetFreePhoto() +{ + return m_bFreePhoto; +} + + +// Indicates whether mouse is on an friend object, on which we should not shoot. + +void CRobotMain::SetFriendAim(BOOL bFriend) +{ + m_bFriendAim = bFriend; +} + +BOOL CRobotMain::RetFriendAim() +{ + return m_bFriendAim; +} + + +// Management of the precision of drawing the ground. + +void CRobotMain::SetTracePrecision(float factor) +{ + m_engine->SetTracePrecision(factor); +} + +float CRobotMain::RetTracePrecision() +{ + return m_engine->RetTracePrecision(); +} + + +// Starts music with a mission. + +void CRobotMain::StartMusic() +{ + if ( m_audioTrack != 0 ) + { + m_sound->StopMusic(); + m_sound->PlayMusic(m_audioTrack, m_bAudioRepeat); + } +} + +// Removes hilite and tooltip. + +void CRobotMain::ClearInterface() +{ + HiliteClear(); // removes setting evidence + m_tooltipName[0] = 0; // really removes the tooltip +} + + diff --git a/src/object/robotmain.h b/src/object/robotmain.h new file mode 100644 index 0000000..bafa62a --- /dev/null +++ b/src/object/robotmain.h @@ -0,0 +1,463 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// robotmain.h + +#ifndef _ROBOTMAIN_H_ +#define _ROBOTMAIN_H_ + + +#include "d3dengine.h" +#include "struct.h" +#include "object.h" +#include "mainmovie.h" +#include "camera.h" +#include "particule.h" + + +enum Phase +{ + PHASE_INIT, + PHASE_TERM, + PHASE_NAME, + PHASE_PERSO, + PHASE_TRAINER, + PHASE_DEFI, + PHASE_MISSION, + PHASE_FREE, + PHASE_TEEN, + PHASE_USER, + PHASE_PROTO, + PHASE_LOADING, + PHASE_SIMUL, + PHASE_MODEL, + PHASE_SETUPd, + PHASE_SETUPg, + PHASE_SETUPp, + PHASE_SETUPc, + PHASE_SETUPs, + PHASE_SETUPds, + PHASE_SETUPgs, + PHASE_SETUPps, + PHASE_SETUPcs, + PHASE_SETUPss, + PHASE_WRITE, + PHASE_READ, + PHASE_WRITEs, + PHASE_READs, + PHASE_WIN, + PHASE_LOST, + PHASE_WELCOME1, + PHASE_WELCOME2, + PHASE_WELCOME3, + PHASE_GENERIC, +}; + + +class CInstanceManager; +class CMainDialog; +class CMainShort; +class CMainMap; +class CEvent; +class CD3DEngine; +class CLight; +class CWater; +class CCloud; +class CBlitz; +class CPlanet; +class CTerrain; +class CModel; +class CInterface; +class CWindow; +class CControl; +class CDisplayText; +class CDisplayInfo; +class CSound; + + +typedef struct +{ + D3DVECTOR pos; + float dist; + ObjectType type; + int min; // wins if> + int max; // wins if < + int lost; // lost if <= + BOOL bImmediat; + char message[100]; +} +EndTake; + + +#define MAXNEWSCRIPTNAME 20 + +typedef struct +{ + BOOL bUsed; + ObjectType type; + char name[40]; +} +NewScriptName; + + +#define MAXSHOWLIMIT 5 +#define MAXSHOWPARTI 200 +#define SHOWLIMITTIME 20.0f + +typedef struct +{ + BOOL bUsed; + D3DVECTOR pos; + float radius; + int total; + int parti[MAXSHOWPARTI]; + CObject* link; + float duration; + float time; +} +ShowLimit; + + +#define SATCOM_HUSTON 0 +#define SATCOM_SAT 1 +#define SATCOM_OBJECT 2 +#define SATCOM_LOADING 3 +#define SATCOM_PROG 4 +#define SATCOM_SOLUCE 5 +#define SATCOM_MAX 6 + + + +class CRobotMain +{ +public: + CRobotMain(CInstanceManager* iMan); + ~CRobotMain(); + + void CreateIni(); + + void ChangePhase(Phase phase); + BOOL EventProcess(const Event &event); + + BOOL CreateShortcuts(); + void ScenePerso(); + + void SetMovieLock(BOOL bLock); + BOOL RetMovieLock(); + BOOL RetInfoLock(); + void SetSatComLock(BOOL bLock); + BOOL RetSatComLock(); + void SetEditLock(BOOL bLock, BOOL bEdit); + BOOL RetEditLock(); + void SetEditFull(BOOL bFull); + BOOL RetEditFull(); + BOOL RetFreePhoto(); + void SetFriendAim(BOOL bFriend); + BOOL RetFriendAim(); + + void SetTracePrecision(float factor); + float RetTracePrecision(); + + void ChangePause(BOOL bPause); + + void SetSpeed(float speed); + float RetSpeed(); + + void UpdateShortcuts(); + void SelectHuman(); + CObject* SearchHuman(); + CObject* SearchToto(); + CObject* SearchNearest(D3DVECTOR pos, CObject* pExclu); + BOOL SelectObject(CObject* pObj, BOOL bDisplayError=TRUE); + CObject* RetSelectObject(); + CObject* DeselectAll(); + BOOL DeleteObject(); + + void ResetObject(); + void ResetCreate(); + Error CheckEndMission(BOOL bFrame); + void CheckEndMessage(char *message); + int RetObligatoryToken(); + char* RetObligatoryToken(int i); + int IsObligatoryToken(char *token); + BOOL IsProhibitedToken(char *token); + void UpdateMap(); + BOOL RetShowMap(); + + MainMovieType RetMainMovie(); + + void FlushDisplayInfo(); + void StartDisplayInfo(int index, BOOL bMovie); + void StartDisplayInfo(char *filename, int index); + void StopDisplayInfo(); + char* RetDisplayInfoName(int index); + int RetDisplayInfoPosition(int index); + void SetDisplayInfoPosition(int index, int pos); + + void StartSuspend(); + void StopSuspend(); + + float RetGameTime(); + + void SetFontSize(float size); + float RetFontSize(); + void SetWindowPos(FPOINT pos); + FPOINT RetWindowPos(); + void SetWindowDim(FPOINT dim); + FPOINT RetWindowDim(); + + void SetIOPublic(BOOL bMode); + BOOL RetIOPublic(); + void SetIOPos(FPOINT pos); + FPOINT RetIOPos(); + void SetIODim(FPOINT dim); + FPOINT RetIODim(); + + char* RetTitle(); + char* RetResume(); + char* RetScriptName(); + char* RetScriptFile(); + BOOL RetTrainerPilot(); + BOOL RetFixScene(); + BOOL RetGlint(); + BOOL RetSoluce4(); + BOOL RetMovies(); + BOOL RetNiceReset(); + BOOL RetHimselfDamage(); + BOOL RetShowSoluce(); + BOOL RetSceneSoluce(); + BOOL RetShowAll(); + BOOL RetCheatRadar(); + char* RetSavegameDir(); + char* RetPublicDir(); + char* RetFilesDir(); + + void SetGamerName(char *name); + char* RetGamerName(); + int RetGamerFace(); + int RetGamerGlasses(); + BOOL RetGamerOnlyHead(); + float RetPersoAngle(); + + void StartMusic(); + void ClearInterface(); + void ChangeColor(); + + float SearchNearestObject(D3DVECTOR center, CObject *exclu); + BOOL FreeSpace(D3DVECTOR ¢er, float minRadius, float maxRadius, float space, CObject *exclu); + float RetFlatZoneRadius(D3DVECTOR center, float maxRadius, CObject *exclu); + void HideDropZone(CObject* metal); + void ShowDropZone(CObject* metal, CObject* truck); + void FlushShowLimit(int i); + void SetShowLimit(int i, ParticuleType parti, CObject *pObj, D3DVECTOR pos, float radius, float duration=SHOWLIMITTIME); + void AdjustShowLimit(int i, D3DVECTOR pos); + void StartShowLimit(); + void FrameShowLimit(float rTime); + + void CompileScript(BOOL bSoluce); + void LoadOneScript(CObject *pObj, int &nbError); + void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nbError); + void SaveAllScript(); + void SaveOneScript(CObject *pObj); + void SaveFileScript(CObject *pObj, char* filename, int objRank); + BOOL SaveFileStack(CObject *pObj, FILE *file, int objRank); + BOOL ReadFileStack(CObject *pObj, FILE *file, int objRank); + + BOOL FlushNewScriptName(); + BOOL AddNewScriptName(ObjectType type, char *name); + char* RetNewScriptName(ObjectType type, int rank); + + void WriteFreeParam(); + void ReadFreeParam(); + + BOOL IsBusy(); + BOOL IOWriteScene(char *filename, char *filecbot, char *info); + CObject* IOReadScene(char *filename, char *filecbot); + void IOWriteObject(FILE *file, CObject* pObj, char *cmd); + CObject* IOReadObject(char *line, char* filename, int objRank); + + int CreateSpot(D3DVECTOR pos, D3DCOLORVALUE color); + +protected: + BOOL EventFrame(const Event &event); + BOOL EventObject(const Event &event); + void InitEye(); + + void Convert(); + void CreateScene(BOOL bSoluce, BOOL bFixScene, BOOL bResetObject); + + void CreateModel(); + D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length ); + CObject* CreateObject(D3DVECTOR pos, float angle, float zoom, float height, ObjectType type, float power=1.0f, BOOL bTrainer=FALSE, BOOL bToy=FALSE, int option=0); + int CreateLight(D3DVECTOR direction, D3DCOLORVALUE color); + void HiliteClear(); + void HiliteObject(FPOINT pos); + void HiliteFrame(float rTime); + void CreateTooltip(FPOINT pos, char* text); + void ClearTooltip(); + CObject* DetectObject(FPOINT pos); + void ChangeCamera(); + void RemoteCamera(float pan, float zoom, float rTime); + void KeyCamera(EventMsg event, long param); + void AbortMovie(); + BOOL IsSelectable(CObject* pObj); + void SelectOneObject(CObject* pObj, BOOL bDisplayError=TRUE); + void HelpObject(); + BOOL DeselectObject(); + void DeleteAllObjects(); + void UpdateInfoText(); + CObject* SearchObject(ObjectType type); + CObject* RetSelect(); + void StartDisplayVisit(EventMsg event); + void FrameVisit(float rTime); + void StopDisplayVisit(); + void ExecuteCmd(char *cmd); + BOOL TestGadgetQuantity(int rank); + +protected: + CInstanceManager* m_iMan; + CMainMovie* m_movie; + CMainDialog* m_dialog; + CMainShort* m_short; + CMainMap* m_map; + CEvent* m_event; + CD3DEngine* m_engine; + CParticule* m_particule; + CWater* m_water; + CCloud* m_cloud; + CBlitz* m_blitz; + CPlanet* m_planet; + CLight* m_light; + CTerrain* m_terrain; + CModel* m_model; + CInterface* m_interface; + CCamera* m_camera; + CDisplayText* m_displayText; + CDisplayInfo* m_displayInfo; + CSound* m_sound; + + float m_time; + float m_gameTime; + float m_checkEndTime; + float m_winDelay; + float m_lostDelay; + BOOL m_bFixScene; // scene fixed, no interraction + BOOL m_bBase; // OBJECT_BASE exists in mission + FPOINT m_lastMousePos; + CObject* m_selectObject; + + Phase m_phase; + int m_cameraRank; + D3DCOLORVALUE m_color; + BOOL m_bFreePhoto; + BOOL m_bCmdEdit; + BOOL m_bShowPos; + BOOL m_bSelectInsect; + BOOL m_bShowSoluce; + BOOL m_bShowAll; + BOOL m_bCheatRadar; + BOOL m_bAudioRepeat; + BOOL m_bShortCut; + int m_audioTrack; + int m_delayWriteMessage; + int m_movieInfoIndex; + + BOOL m_bImmediatSatCom; // SatCom immediately? + BOOL m_bBeginSatCom; // messages SatCom poster? + BOOL m_bMovieLock; // movie in progress? + BOOL m_bSatComLock; // call of SatCom is possible? + BOOL m_bEditLock; // edition in progress? + BOOL m_bEditFull; // edition in full screen? + BOOL m_bPause; // simulation paused + BOOL m_bHilite; + BOOL m_bTrainerPilot; // remote trainer? + BOOL m_bSuspend; + BOOL m_bFriendAim; + BOOL m_bResetCreate; + BOOL m_bMapShow; + BOOL m_bMapImage; + char m_mapFilename[100]; + + FPOINT m_tooltipPos; + char m_tooltipName[100]; + float m_tooltipTime; + + char m_infoFilename[SATCOM_MAX][100]; // names of text files + CObject* m_infoObject; + int m_infoIndex; + int m_infoPos[SATCOM_MAX]; + int m_infoUsed; + + char m_title[100]; + char m_resume[500]; + char m_scriptName[100]; + char m_scriptFile[100]; + int m_endingWinRank; + int m_endingLostRank; + BOOL m_bWinTerminate; + + float m_fontSize; + FPOINT m_windowPos; + FPOINT m_windowDim; + + BOOL m_IOPublic; + FPOINT m_IOPos; + FPOINT m_IODim; + + NewScriptName m_newScriptName[MAXNEWSCRIPTNAME]; + + float m_cameraPan; + float m_cameraZoom; + + EventMsg m_visitLast; + CObject* m_visitObject; + CObject* m_visitArrow; + float m_visitTime; + float m_visitParticule; + D3DVECTOR m_visitPos; + D3DVECTOR m_visitPosArrow; + + int m_endTakeTotal; + EndTake m_endTake[10]; + long m_endTakeResearch; + float m_endTakeWinDelay; + float m_endTakeLostDelay; + + int m_obligatoryTotal; + char m_obligatoryToken[100][20]; + int m_prohibitedTotal; + char m_prohibitedToken[100][20]; + + char m_gamerName[100]; + + long m_freeBuild; // constructible buildings + long m_freeResearch; // researches possible + + ShowLimit m_showLimit[MAXSHOWLIMIT]; + + D3DCOLORVALUE m_colorRefBot; + D3DCOLORVALUE m_colorNewBot; + D3DCOLORVALUE m_colorRefAlien; + D3DCOLORVALUE m_colorNewAlien; + D3DCOLORVALUE m_colorRefGreen; + D3DCOLORVALUE m_colorNewGreen; + D3DCOLORVALUE m_colorRefWater; + D3DCOLORVALUE m_colorNewWater; + float m_colorShiftWater; +}; + + +#endif //_ROBOTMAIN_H_ diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp new file mode 100644 index 0000000..6b8222e --- /dev/null +++ b/src/object/task/task.cpp @@ -0,0 +1,109 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// task.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "motion.h" +#include "camera.h" +#include "sound.h" +#include "robotmain.h" +#include "displaytext.h" +#include "task.h" + + + + +// Object's constructor. + +CTask::CTask(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT); + m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND); + + m_object = object; + m_physics = m_object->RetPhysics(); + m_brain = m_object->RetBrain(); + m_motion = m_object->RetMotion(); +} + +// Object's destructor. + +CTask::~CTask() +{ +} + + +// Management of an event. + +BOOL CTask::EventProcess(const Event &event) +{ + return TRUE; +} + + +// Indicates whether the action is finished. + +Error CTask::IsEnded() +{ + return ERR_STOP; +} + + +// Indicates whether the action is pending. + +BOOL CTask::IsBusy() +{ + return TRUE; +} + + +// Suddenly ends the current action. + +BOOL CTask::Abort() +{ + return TRUE; +} + + diff --git a/src/object/task/task.h b/src/object/task/task.h new file mode 100644 index 0000000..f5685ef --- /dev/null +++ b/src/object/task/task.h @@ -0,0 +1,89 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// task.h + +#ifndef _TASK_H_ +#define _TASK_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CD3DEngine; +class CEngine; +class CLight; +class CParticule; +class CTerrain; +class CWater; +class CCamera; +class CBrain; +class CPhysics; +class CMotion; +class CObject; +class CRobotMain; +class CDisplayText; +class CSound; + + +#define TAKE_DIST 6.0f // distance to an object to pick it +#define TAKE_DIST_OTHER 1.5f // additional distance if on friend + +//?#define ARM_NEUTRAL_ANGLE1 155.0f*PI/180.0f +//?#define ARM_NEUTRAL_ANGLE2 -125.0f*PI/180.0f +//?#define ARM_NEUTRAL_ANGLE3 -45.0f*PI/180.0f +#define ARM_NEUTRAL_ANGLE1 110.0f*PI/180.0f +#define ARM_NEUTRAL_ANGLE2 -130.0f*PI/180.0f +#define ARM_NEUTRAL_ANGLE3 -50.0f*PI/180.0f + +#define ARM_STOCK_ANGLE1 110.0f*PI/180.0f +#define ARM_STOCK_ANGLE2 -100.0f*PI/180.0f +#define ARM_STOCK_ANGLE3 -70.0f*PI/180.0f + + +class CTask +{ +public: + CTask(CInstanceManager* iMan, CObject* object); + virtual ~CTask(); + + virtual BOOL EventProcess(const Event &event); + virtual Error IsEnded(); + virtual BOOL IsBusy(); + virtual BOOL Abort(); + +protected: + +protected: + CInstanceManager* m_iMan; + CD3DEngine* m_engine; + CLight* m_light; + CParticule* m_particule; + CTerrain* m_terrain; + CWater* m_water; + CCamera* m_camera; + CMotion* m_motion; + CBrain* m_brain; + CPhysics* m_physics; + CObject* m_object; + CRobotMain* m_main; + CDisplayText* m_displayText; + CSound* m_sound; +}; + + +#endif //_TASK_H_ diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp new file mode 100644 index 0000000..7860cb2 --- /dev/null +++ b/src/object/task/taskadvance.cpp @@ -0,0 +1,159 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskadvance.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "task.h" +#include "taskadvance.h" + + + + +// Object's constructor. + +CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskAdvance::~CTaskAdvance() +{ +} + + +// Management of an event. + +BOOL CTaskAdvance::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_fixTime += event.rTime; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_bError = TRUE; + return TRUE; + } + + m_timeLimit -= event.rTime; + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskAdvance::Start(float length) +{ + m_direction = (length>=0.0f)?1.0f:-1.0f; + m_totalLength = Abs(length); + m_advanceLength = m_physics->RetLinLength(length); + m_startPos = m_object->RetPosition(0); + m_lastDist = 0.0f; + m_fixTime = 0.0f; + + m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f; + if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f; + + m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward + m_physics->SetMotorSpeedY(0.0f); + m_physics->SetMotorSpeedZ(0.0f); + + m_bError = FALSE; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskAdvance::IsEnded() +{ + D3DVECTOR pos; + float length; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + return ERR_STOP; + } + + if ( m_timeLimit < 0.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + return ERR_MOVE_IMPOSSIBLE; + } + + pos = m_object->RetPosition(0); + length = Length2d(pos, m_startPos); + + if ( length > m_lastDist ) // forward? + { + m_fixTime = 0.0f; + } + else // still stands? + { + if ( m_fixTime > 1.0f ) // for more than a second? + { + m_physics->SetMotorSpeedX(0.0f); + return ERR_MOVE_IMPOSSIBLE; + } + } + m_lastDist = length; + + if ( length >= m_totalLength ) + { + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetLinMotionX(MO_CURSPEED, 0.0f); + + if ( length != 0.0f ) + { + pos = m_startPos+((pos-m_startPos)*m_totalLength/length); + m_object->SetPosition(0, pos); + } + return ERR_STOP; + } + + if ( length >= m_advanceLength ) + { + m_physics->SetMotorSpeedX(m_direction*0.1f); + } + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskadvance.h b/src/object/task/taskadvance.h new file mode 100644 index 0000000..284cf12 --- /dev/null +++ b/src/object/task/taskadvance.h @@ -0,0 +1,59 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskadvance.h + +#ifndef _TASKADVANCE_H_ +#define _TASKADVANCE_H_ + + +#include "misc.h" +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskAdvance : public CTask +{ +public: + CTaskAdvance(CInstanceManager* iMan, CObject* object); + ~CTaskAdvance(); + + BOOL EventProcess(const Event &event); + + Error Start(float length); + Error IsEnded(); + +protected: + +protected: + float m_totalLength; + float m_advanceLength; + float m_direction; + float m_timeLimit; + D3DVECTOR m_startPos; + float m_lastDist; + float m_fixTime; + BOOL m_bError; +}; + + +#endif //_TASKADVANCE_H_ diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp new file mode 100644 index 0000000..cc1303b --- /dev/null +++ b/src/object/task/taskbuild.cpp @@ -0,0 +1,822 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskbuild.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "light.h" +#include "particule.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "auto.h" +#include "camera.h" +#include "motion.h" +#include "motionhuman.h" +#include "robotmain.h" +#include "sound.h" +#include "displaytext.h" +#include "task.h" +#include "taskbuild.h" + + + + +// Object's constructor. + +CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + int i; + + CTask::CTask(iMan, object); + + m_type = OBJECT_DERRICK; + m_time = 0.0f; + m_soundChannel = -1; + + for ( i=0 ; iFlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + for ( i=0 ; iDeleteLight(m_lightRank[i]); + } +} + + +// Creates a building. + +BOOL CTaskBuild::CreateBuilding(D3DVECTOR pos, float angle) +{ + m_building = new CObject(m_iMan); + if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) ) + { + delete m_building; + m_building = 0; + return FALSE; + } + m_building->UpdateMapping(); + m_building->SetLock(TRUE); // not yet usable + + if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f; + if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f; + if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f; + if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f; + if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f; + if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f; + if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f; + if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f; + if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f; + if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f; + if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f; + if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f; + if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f; + m_buildingHeight *= 0.25f; + + m_buildingPos = m_building->RetPosition(0); + m_buildingPos.y -= m_buildingHeight; + m_building->SetPosition(0, m_buildingPos); + return TRUE; +} + +// Creates lights for the effects. + +void CTaskBuild::CreateLight() +{ + D3DLIGHT7 light; + D3DCOLORVALUE color; + D3DVECTOR center, pos, dir; + FPOINT c, p; + float angle; + int i; + + if ( !m_engine->RetLightMode() ) return; + + center = m_metal->RetPosition(0); + + angle = 0; + for ( i=0 ; iCreateLight(); + if ( m_lightRank[i] == -1 ) continue; + + c.x = center.x; + c.y = center.z; + p.x = center.x+40.0f; + p.y = center.z; + p = RotatePoint(c, angle, p); + pos.x = p.x; + pos.z = p.y; + pos.y = center.y+40.0f; + dir = center-pos; + + ZeroMemory( &light, sizeof(light) ); + light.dltType = D3DLIGHT_SPOT; + light.dcvDiffuse.r = 0.0f; + light.dcvDiffuse.g = 0.0f; + light.dcvDiffuse.b = 0.0f; // white (invisible) + light.dvPosition.x = pos.x; + light.dvPosition.y = pos.y; + light.dvPosition.z = pos.z; + light.dvDirection.x = dir.x; + light.dvDirection.y = dir.y; + light.dvDirection.z = dir.z; + light.dvRange = D3DLIGHT_RANGE_MAX; + light.dvFalloff = 1.0f; + light.dvAttenuation0 = 1.0f; + light.dvAttenuation1 = 0.0f; + light.dvAttenuation2 = 0.0f; + light.dvTheta = 0.0f; + light.dvPhi = PI/4.0f; + m_light->SetLight(m_lightRank[i], light); + + color.r = -1.0f; + color.g = -1.0f; + color.b = -0.5f; // violet + color.a = 0.0f; + m_light->SetLightColor(m_lightRank[i], color); + m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f)); + + angle += (PI*2.0f)/TBMAXLIGHT; + } + + m_bBlack = FALSE; +} + +// Switches the lights from black to white. + +void CTaskBuild::BlackLight() +{ + D3DCOLORVALUE color; + int i; + + for ( i=0 ; iSetLightColor(m_lightRank[i], color); + m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f)); + } + + m_bBlack = TRUE; +} + +// Management of an event. + +BOOL CTaskBuild::EventProcess(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR pos, dir, speed; + FPOINT dim; + float a, g, cirSpeed, dist, linSpeed; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_time += event.rTime; + + m_progress += event.rTime*m_speed; // other advance + + if ( m_phase == TBP_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angleY; + cirSpeed = Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right + return TRUE; + } + + if ( m_phase == TBP_MOVE ) // preliminary forward/backward? + { + dist = Length(m_object->RetPosition(0), m_metal->RetPosition(0)); + linSpeed = 0.0f; + if ( dist > 30.0f ) linSpeed = 1.0f; + if ( dist < 30.0f ) linSpeed = -1.0f; + m_physics->SetMotorSpeedX(linSpeed); // forward/backward + return TRUE; + } + + if ( m_phase == TBP_RECEDE ) // terminal back? + { + m_physics->SetMotorSpeedX(-1.0f); // back + return TRUE; + } + + if ( m_phase == TBP_TAKE ) // takes gun? + { + return TRUE; + } + + if ( m_phase == TBP_PREP ) // prepares? + { + return TRUE; + } + + if ( m_phase == TBP_TERM ) // ends? + { + return TRUE; + } + + if ( !m_bBuild ) // building to build? + { + m_bBuild = TRUE; + + pos = m_metal->RetPosition(0); + a = m_object->RetAngleY(0); + if ( !CreateBuilding(pos, a+PI) ) + { + m_metal->SetLock(FALSE); // usable again + m_motion->SetAction(-1); + m_object->SetObjectParent(14, 0); + m_object->SetPosition(14, D3DVECTOR(-1.5f, 0.3f, -1.35f)); + m_object->SetAngleZ(14, PI); + m_camera->FlushEffect(); + Abort(); + m_bError = TRUE; + m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0)); + return FALSE; + } + CreateLight(); + } + + pos = m_buildingPos; + pos.y += m_buildingHeight*m_progress; + m_building->SetPosition(0, pos); // the building rises + + m_building->SetZoom(0, m_progress*0.75f+0.25f); + m_metal->SetZoom(0, 1.0f-m_progress); + + a = (2.0f-2.0f*m_progress); + if ( a > 1.0f ) a = 1.0f; + dir.x = (Rand()-0.5f)*a*0.1f; + dir.z = (Rand()-0.5f)*a*0.1f; + dir.y = (Rand()-0.5f)*a*0.1f; + m_building->SetCirVibration(dir); + + if ( !m_bBlack && m_progress >= 0.25f ) + { + BlackLight(); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_metal->RetPosition(0); + speed.x = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + speed.y = Rand()*10.0f; + dim.x = Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIRE); + + pos = D3DVECTOR(0.0f, 0.5f, 0.0f); + mat = m_object->RetWorldMatrix(14); + pos = Transform(*mat, pos); + speed = m_metal->RetPosition(0); + speed.x += (Rand()-0.5f)*5.0f; + speed.z += (Rand()-0.5f)*5.0f; + speed -= pos; + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ); + + if ( Rand() < 0.3f ) + { + m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Rand()*1.5f); + } + } + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskBuild::Start(ObjectType type) +{ + D3DVECTOR pos, speed, pv, pm; + Error err; + float iAngle, oAngle; + + m_type = type; + m_lastParticule = 0.0f; + m_progress = 0.0f; + + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + oAngle = iAngle; + + m_bError = TRUE; // operation impossible + + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER; + + if ( !m_physics->RetLand() ) return ERR_BUILD_FLY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_BUILD_MOTOR; + + if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY; + + m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, PI*0.25f, err); + if ( err == ERR_BUILD_METALNEAR && m_metal != 0 ) + { + err = FlatFloor(); + if ( err != ERR_OK ) return err; + return ERR_BUILD_METALNEAR; + } + if ( err != ERR_OK ) return err; + + err = FlatFloor(); + if ( err != ERR_OK ) return err; + + m_metal->SetLock(TRUE); // not usable + m_camera->StartCentering(m_object, PI*0.15f, 99.9f, 0.0f, 1.0f); + + m_phase = TBP_TURN; // rotation necessary preliminary + m_angleY = oAngle; // angle was reached + + pv = m_object->RetPosition(0); + pv.y += 8.3f; + pm = m_metal->RetPosition(0); + m_angleZ = RotateAngle(Length2d(pv, pm), Abs(pv.y-pm.y)); + + m_physics->SetFreeze(TRUE); // it does not move + + m_bBuild = FALSE; // not yet built + m_bError = FALSE; // ok + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskBuild::IsEnded() +{ + CAuto* automat; + float angle, dist, time; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TBP_TURN ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = NormAngle(angle); // 0..2*PI + + if ( TestAngle(angle, m_angleY-PI*0.01f, m_angleY+PI*0.01f) ) + { + m_physics->SetMotorSpeedZ(0.0f); + + dist = Length(m_object->RetPosition(0), m_metal->RetPosition(0)); + if ( dist > 30.0f ) + { + time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f); + m_speed = 1.0f/time; + } + else + { + time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f); + m_speed = 1.0f/time; + } + m_phase = TBP_MOVE; + m_progress = 0.0f; + } + return ERR_CONTINUE; + } + + if ( m_phase == TBP_MOVE ) // preliminary forward/backward? + { + dist = Length(m_object->RetPosition(0), m_metal->RetPosition(0)); + + if ( dist >= 25.0f && dist <= 35.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + m_motion->SetAction(MHS_GUN); // takes gun + + m_phase = TBP_TAKE; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + else + { + if ( m_progress > 1.0f ) // timeout? + { + m_metal->SetLock(FALSE); // usable again + if ( dist < 30.0f ) return ERR_BUILD_METALNEAR; + else return ERR_BUILD_METALAWAY; + } + } + return ERR_CONTINUE; + } + + if ( m_phase == TBP_TAKE ) // takes gun + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_motion->SetAction(MHS_FIRE); // shooting position + m_object->SetObjectParent(14, 4); + m_object->SetPosition(14, D3DVECTOR(0.6f, 0.1f, 0.3f)); + m_object->SetAngleZ(14, 0.0f); + + m_phase = TBP_PREP; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + if ( m_phase == TBP_PREP ) // prepares? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP); + + m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f); + + m_phase = TBP_BUILD; + m_speed = 1.0f/10.f; // duration of 10s + m_progress = 0.0f; + } + + if ( m_phase == TBP_BUILD ) // construction? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + DeleteMark(m_metal->RetPosition(0), 20.0f); + + m_metal->DeleteObject(); // removes the metal + delete m_metal; + m_metal = 0; + + m_building->SetZoom(0, 1.0f); + m_building->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_building->SetLock(FALSE); // building usable + m_main->CreateShortcuts(); + m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f); + + automat = m_building->RetAuto(); + if ( automat != 0 ) + { + automat->Init(); + } + + m_motion->SetAction(MHS_GUN); // hands gun + m_phase = TBP_TERM; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + if ( m_phase == TBP_TERM ) // rotation terminale ? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_motion->SetAction(-1); + m_object->SetObjectParent(14, 0); + m_object->SetPosition(14, D3DVECTOR(-1.5f, 0.3f, -1.35f)); + m_object->SetAngleZ(14, PI); + + if ( m_type == OBJECT_FACTORY || + m_type == OBJECT_RESEARCH || + m_type == OBJECT_NUCLEAR ) + { + + m_phase = TBP_RECEDE; + m_speed = 1.0f/1.5f; + m_progress = 0.0f; + } + } + + if ( m_phase == TBP_RECEDE ) // back? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedX(0.0f); + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskBuild::Abort() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(FALSE); // is moving again + return TRUE; +} + + +// Checks whether the terrain is fairly flat +// and if there is not too close to another object. + +Error CTaskBuild::FlatFloor() +{ + CObject *pObj; + ObjectType type; + D3DVECTOR center, pos, oPos, bPos; + FPOINT c, p; + float radius, max, oRadius, bRadius, angle, dist; + int i, j; + BOOL bLittleFlat, bBase; + + radius = 0.0f; + if ( m_type == OBJECT_DERRICK ) radius = 5.0f; + if ( m_type == OBJECT_FACTORY ) radius = 15.0f; + if ( m_type == OBJECT_REPAIR ) radius = 12.0f; + if ( m_type == OBJECT_STATION ) radius = 12.0f; + if ( m_type == OBJECT_CONVERT ) radius = 12.0f; + if ( m_type == OBJECT_TOWER ) radius = 7.0f; + if ( m_type == OBJECT_RESEARCH ) radius = 10.0f; + if ( m_type == OBJECT_RADAR ) radius = 5.0f; + if ( m_type == OBJECT_ENERGY ) radius = 8.0f; + if ( m_type == OBJECT_LABO ) radius = 12.0f; + if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f; + if ( m_type == OBJECT_PARA ) radius = 20.0f; + if ( m_type == OBJECT_INFO ) radius = 5.0f; + if ( radius == 0.0f ) return ERR_GENERIC; + + center = m_metal->RetPosition(0); + angle = m_terrain->RetFineSlope(center); + bLittleFlat = ( angle < FLATLIMIT ); + + max = m_terrain->RetFlatZoneRadius(center, radius); + if ( max < radius ) // area too small? + { + if ( bLittleFlat ) + { + m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f); + } + return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT; + } + + max = 100000.0f; + bBase = FALSE; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj == m_metal ) continue; + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_BASE ) + { + oPos = pObj->RetPosition(0); + dist = Length(center, oPos)-80.0f; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + bBase = TRUE; + } + } + else + { + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Length(center, oPos)-oRadius; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + bBase = FALSE; + } + } + } + } + if ( max < radius ) + { + m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f); + if ( bRadius < 2.0f ) bRadius = 2.0f; + m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f); + return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY; + } + + max = 100000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj == m_metal ) continue; + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type == OBJECT_DERRICK || + type == OBJECT_FACTORY || + type == OBJECT_STATION || + type == OBJECT_CONVERT || + type == OBJECT_REPAIR || + type == OBJECT_TOWER || + type == OBJECT_RESEARCH || + type == OBJECT_RADAR || + type == OBJECT_ENERGY || + type == OBJECT_LABO || + type == OBJECT_NUCLEAR || + type == OBJECT_START || + type == OBJECT_END || + type == OBJECT_INFO || + type == OBJECT_PARA || + type == OBJECT_SAFE || + type == OBJECT_HUSTON ) // building? + { + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Length(center, oPos)-oRadius; + if ( dist < max ) + { + max = dist; + bPos = oPos; + bRadius = oRadius; + } + } + } + } + if ( max-BUILDMARGIN < radius ) + { + m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f); + m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f); + return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW; + } + + return ERR_OK; +} + +// Seeks the nearest metal object. + +CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax, + float aLimit, Error &err) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float min, iAngle, a, aa, aBest, distance, magic; + int i; + BOOL bMetal; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + min = 1000000.0f; + pBest = 0; + bMetal = FALSE; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; // objet inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + type = pObj->RetType(); + if ( type != OBJECT_METAL ) continue; + + bMetal = TRUE; // metal exists + + oPos = pObj->RetPosition(0); + distance = Length(oPos, iPos); + a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW! + + if ( distance > dMax ) continue; + if ( !TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue; + + if ( distance < dMin ) + { + err = ERR_BUILD_METALNEAR; // too close + return pObj; + } + + aa = Abs(a-iAngle); + if ( aa > PI ) aa = PI*2.0f-aa; + magic = distance*aa; + + if ( magic < min ) + { + min = magic; + aBest = a; + pBest = pObj; + } + } + + if ( pBest == 0 ) + { + if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far + else err = ERR_BUILD_METALINEX; // non-existent + } + else + { + angle = aBest; + err = ERR_OK; + } + return pBest; +} + +// Destroys all the close marks. + +void CTaskBuild::DeleteMark(D3DVECTOR pos, float radius) +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float distance; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_MARKSTONE && + type != OBJECT_MARKURANIUM && + type != OBJECT_MARKKEYa && + type != OBJECT_MARKKEYb && + type != OBJECT_MARKKEYc && + type != OBJECT_MARKKEYd && + type != OBJECT_MARKPOWER ) continue; + + oPos = pObj->RetPosition(0); + distance = Length(oPos, pos); + if ( distance <= radius ) + { + pObj->DeleteObject(); // removes the mark + delete pObj; + i --; + } + } +} + diff --git a/src/object/task/taskbuild.h b/src/object/task/taskbuild.h new file mode 100644 index 0000000..75a44f7 --- /dev/null +++ b/src/object/task/taskbuild.h @@ -0,0 +1,93 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskbuild.h + +#ifndef _TASKBUILD_H_ +#define _TASKBUILD_H_ + + +#include "misc.h" +#include "object.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; + + + +#define BUILDMARGIN 16.0f +#define TBMAXLIGHT 4 + + +enum TaskBuildPhase +{ + TBP_TURN = 1, // turns + TBP_MOVE = 2, // forward/backward + TBP_TAKE = 3, // takes gun + TBP_PREP = 4, // prepares + TBP_BUILD = 5, // builds + TBP_TERM = 6, // ends + TBP_RECEDE = 7, // back terminal +}; + + + +class CTaskBuild : public CTask +{ +public: + CTaskBuild(CInstanceManager* iMan, CObject* object); + ~CTaskBuild(); + + BOOL EventProcess(const Event &event); + + Error Start(ObjectType type); + Error IsEnded(); + BOOL Abort(); + +protected: + Error FlatFloor(); + BOOL CreateBuilding(D3DVECTOR pos, float angle); + void CreateLight(); + void BlackLight(); + CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err); + void DeleteMark(D3DVECTOR pos, float radius); + +protected: + ObjectType m_type; // type of construction + CObject* m_metal; // transforms metal object + CObject* m_power; // the vehicle battery + CObject* m_building; // building built + TaskBuildPhase m_phase; // phase of the operation + BOOL m_bError; // TRUE -> operation impossible + BOOL m_bBuild; // TRUE -> building built + BOOL m_bBlack; // TRUE -> lights black -> white + float m_time; // absolute time + float m_lastParticule; // time of generation last particle + float m_progress; // progression (0..1) + float m_speed; // speed of progression + float m_angleY; // rotation angle of the vehicle + float m_angleZ; // angle of rotation of the gun + D3DVECTOR m_buildingPos; // initial position of the building + float m_buildingHeight; // height of the building + int m_lightRank[TBMAXLIGHT];// lights for the effects + int m_soundChannel; +}; + + +#endif //_TASKBUILD_H_ diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp new file mode 100644 index 0000000..4fc0af5 --- /dev/null +++ b/src/object/task/taskfire.cpp @@ -0,0 +1,398 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskfire.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "task.h" +#include "taskfire.h" + + + +#define ENERGY_FIRE (0.25f/2.5f) // energy consumed/shot +#define ENERGY_FIREr (0.25f/1.5f) // energy consumed/ray +#define ENERGY_FIREi (0.10f/2.5f) // energy consumed/organic + + +// Object's constructor. + +CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + m_soundChannel = -1; +} + +// Object's destructor. + +CTaskFire::~CTaskFire() +{ + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } +} + + +// Management of an event. + +BOOL CTaskFire::EventProcess(const Event &event) +{ + CObject* power; + CPhysics* physics; + D3DMATRIX* mat; + D3DVECTOR pos, speed, dir, vib; + ObjectType type; + FPOINT dim; + float energy, fire; + int i, channel; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_time += event.rTime; + m_lastSound -= event.rTime; + m_progress += event.rTime*m_speed; + + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + if ( m_bOrganic ) fire = ENERGY_FIREi; + else if ( m_bRay ) fire = ENERGY_FIREr; + else fire = ENERGY_FIRE; + energy -= event.rTime*fire/power->RetCapacity(); + power->SetEnergy(energy); + } + + if ( m_lastParticule+0.05f <= m_time ) + { + m_lastParticule = m_time; + + if ( m_bOrganic ) + { + mat = m_object->RetWorldMatrix(1); // insect-cannon + + for ( i=0 ; i<6 ; i++ ) + { + pos = D3DVECTOR(0.0f, 2.5f, 0.0f); + pos = Transform(*mat, pos); + + speed = D3DVECTOR(200.0f, 0.0f, 0.0f); + + physics = m_object->RetPhysics(); + if ( physics != 0 ) + { + speed += physics->RetLinMotion(MO_REASPEED); + } + + speed.x += (Rand()-0.5f)*10.0f; + speed.y += (Rand()-0.5f)*20.0f; + speed.z += (Rand()-0.5f)*30.0f; + speed = Transform(*mat, speed); + speed -= pos; + + dim.x = Rand()*0.5f+0.5f; + dim.y = dim.x; + + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + } + else if ( m_bRay ) + { + mat = m_object->RetWorldMatrix(2); // cannon + + for ( i=0 ; i<4 ; i++ ) + { + pos = D3DVECTOR(4.0f, 0.0f, 0.0f); + pos.y += (rand()%3-1)*1.5f; + pos.z += (rand()%3-1)*1.5f; + pos = Transform(*mat, pos); + + speed = D3DVECTOR(200.0f, 0.0f, 0.0f); + speed.x += (Rand()-0.5f)*6.0f; + speed.y += (Rand()-0.5f)*12.0f; + speed.z += (Rand()-0.5f)*12.0f; + speed = Transform(*mat, speed); + speed -= pos; + + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11, + 2.0f, 200.0f, 0.5f, 1.0f); + m_particule->SetObjectFather(channel, m_object); + + speed = D3DVECTOR(5.0f, 0.0f, 0.0f); + speed.x += (Rand()-0.5f)*1.0f; + speed.y += (Rand()-0.5f)*2.0f; + speed.z += (Rand()-0.5f)*2.0f; + speed = Transform(*mat, speed); + speed -= pos; + speed.y += 5.0f; + + dim.x = 2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f); + } + } + else + { + type = m_object->RetType(); + + if ( type == OBJECT_MOBILErc ) + { + mat = m_object->RetWorldMatrix(2); // cannon + } + else + { + mat = m_object->RetWorldMatrix(1); // cannon + } + + for ( i=0 ; i<3 ; i++ ) + { + if ( type == OBJECT_MOBILErc ) + { + pos = D3DVECTOR(0.0f, 0.0f, 0.0f); + } + else + { + pos = D3DVECTOR(3.0f, 1.0f, 0.0f); + } + pos.y += (Rand()-0.5f)*1.0f; + pos.z += (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + + speed = D3DVECTOR(200.0f, 0.0f, 0.0f); + + physics = m_object->RetPhysics(); + if ( physics != 0 ) + { + speed += physics->RetLinMotion(MO_REASPEED); + } + + speed.x += (Rand()-0.5f)*3.0f; + speed.y += (Rand()-0.5f)*6.0f; + speed.z += (Rand()-0.5f)*6.0f; + speed = Transform(*mat, speed); + speed -= pos; + + dim.x = Rand()*0.7f+0.7f; + dim.y = dim.x; + + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + + if ( type != OBJECT_MOBILErc && + m_progress > 0.3f ) + { + pos = D3DVECTOR(-1.0f, 1.0f, 0.0f); + pos.y += (Rand()-0.5f)*0.4f; + pos.z += (Rand()-0.5f)*0.4f; + pos = Transform(*mat, pos); + + speed = D3DVECTOR(-4.0f, 0.0f, 0.0f); + speed.x += (Rand()-0.5f)*2.0f; + speed.y += (Rand()-0.2f)*4.0f; + speed.z += (Rand()-0.5f)*4.0f; + speed = Transform(*mat, speed); + speed -= pos; + + dim.x = Rand()*1.2f+1.2f; + dim.y = dim.x; + + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f); +//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f); + } + } + + dir = D3DVECTOR(0.0f, 0.0f, 0.0f); + if ( m_progress < 0.1f ) + { + dir.z = (PI*0.04f)*(m_progress*10.0f); + } + else if ( m_progress < 0.9f ) + { + dir.z = (PI*0.04f); + } + else + { + dir.z = (PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f); + } + m_object->SetInclinaison(dir); + + vib.x = (Rand()-0.5f)*0.01f; + vib.y = (Rand()-0.5f)*0.02f; + vib.z = (Rand()-0.5f)*0.02f; + m_object->SetCirVibration(vib); + + vib.x = (Rand()-0.5f)*0.20f; + vib.y = (Rand()-0.5f)*0.05f; + vib.z = (Rand()-0.5f)*0.20f; + m_object->SetLinVibration(vib); + } + + if ( m_bRay && m_lastSound <= 0.0f ) + { + m_lastSound = Rand()*0.4f+0.4f; + m_sound->Play(SOUND_FIREp, m_object->RetPosition(0)); + } + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskFire::Start(float delay) +{ + CObject* power; + D3DVECTOR pos, goal, speed; + float energy, fire; + ObjectType type; + + m_bError = TRUE; // operation impossible + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILErc ) return ERR_FIRE_VEH; + +//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY; + + speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_FIRE_MOTOR; + + m_bRay = (type == OBJECT_MOBILErc); + + m_bOrganic = FALSE; + if ( type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii ) + { + m_bOrganic = TRUE; + } + + if ( delay == 0.0f ) + { + if ( m_bRay ) delay = 1.2f; + else delay = 2.0f; + } + m_delay = delay; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_FIRE_ENERGY; + energy = power->RetEnergy(); + if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi; + else if ( m_bRay ) fire = m_delay*ENERGY_FIREr; + else fire = m_delay*ENERGY_FIRE; + if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY; + + m_speed = 1.0f/m_delay; + m_progress = 0.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_lastSound = 0.0f; + m_bError = FALSE; // ok + +//? m_camera->StartCentering(m_object, PI*0.15f, 99.9f, 0.0f, 1.0f); + + if ( m_bOrganic ) + { + m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, TRUE); + if ( m_soundChannel != -1 ) + { + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP); + } + } + else if ( m_bRay ) + { + } + else + { + m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, TRUE); + if ( m_soundChannel != -1 ) + { + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP); + } + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFire::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskFire::Abort() +{ + m_object->SetInclinaison(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetLinVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + +//? m_camera->StopCentering(m_object, 1.0f); + return TRUE; +} + diff --git a/src/object/task/taskfire.h b/src/object/task/taskfire.h new file mode 100644 index 0000000..af371b2 --- /dev/null +++ b/src/object/task/taskfire.h @@ -0,0 +1,61 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskfire.h + +#ifndef _TASKFIRE_H_ +#define _TASKTIRE_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskFire : public CTask +{ +public: + CTaskFire(CInstanceManager* iMan, CObject* object); + ~CTaskFire(); + + BOOL EventProcess(const Event &event); + + Error Start(float delay); + Error IsEnded(); + BOOL Abort(); + +protected: + +protected: + float m_delay; + float m_progress; + BOOL m_bError; + BOOL m_bRay; + BOOL m_bOrganic; + float m_time; + float m_speed; + float m_lastParticule; + float m_lastSound; + int m_soundChannel; +}; + + +#endif //_TASKFIRE_H_ diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp new file mode 100644 index 0000000..2c47adf --- /dev/null +++ b/src/object/task/taskfireant.cpp @@ -0,0 +1,227 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskfireant.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "motion.h" +#include "motionant.h" +#include "task.h" +#include "taskfireant.h" + + + + +// Object's constructor. + +CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_phase = TFA_NULL; +} + +// Object's destructor. + +CTaskFireAnt::~CTaskFireAnt() +{ +} + + +// Management of an event. + +BOOL CTaskFireAnt::EventProcess(const Event &event) +{ + D3DVECTOR dir, vib; + float a, g, cirSpeed; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + if ( m_object->RetFixed() ) // insect on its back? + { + m_bError = TRUE; + return FALSE; + } + + m_time += event.rTime; + m_progress += event.rTime*m_speed; + + if ( m_phase == TFA_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Direction(a, g)*2.0f; + if ( cirSpeed > 2.0f ) cirSpeed = 2.0f; + if ( cirSpeed < -2.0f ) cirSpeed = -2.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right + } + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskFireAnt::Start(D3DVECTOR impact) +{ + D3DVECTOR pos; + ObjectType type; + + m_impact = impact; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) return ERR_FIRE_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_ANT ) return ERR_FIRE_VEH; + + // Insect on its back? + if ( m_object->RetFixed() ) return ERR_FIRE_VEH; + + m_physics->SetMotorSpeed(D3DVECTOR(0.0f, 0.0f, 0.0f)); + + pos = m_object->RetPosition(0); + m_angle = RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW ! + + m_phase = TFA_TURN; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + m_bError = FALSE; // ok + m_bFire = FALSE; // once! + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFireAnt::IsEnded() +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed; + FPOINT dim; + float angle, dist; + int i, channel; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back? + + if ( m_phase == TFA_TURN ) // rotation ? + { + angle = m_object->RetAngleY(0); + angle = NormAngle(angle); // 0..2*PI + if ( !TestAngle(angle, m_angle-PI*0.05f, m_angle+PI*0.05f) ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedZ(0.0f); // rotation ended + + m_phase = TFA_PREPARE; +//? m_speed = 1.0f/1.5f; + m_speed = 1.0f/0.4f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_PREPARE, 1.5f); + m_motion->SetAction(MAS_PREPARE, 0.4f); + } + + if ( m_phase == TFA_PREPARE ) // preparation? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_FIRE; +//? m_speed = 1.0f/2.0f; + m_speed = 1.0f/0.5f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_FIRE, 2.0f); + m_motion->SetAction(MAS_FIRE, 0.5f); + } + + if ( m_phase == TFA_FIRE ) // shooting? + { + if ( m_progress > 0.75f && !m_bFire ) + { + m_bFire = TRUE; // once + + for ( i=0 ; i<20 ; i++ ) + { + pos = D3DVECTOR(-2.5f, -0.7f, 0.0f); + mat = m_object->RetWorldMatrix(2); + pos = Transform(*mat, pos); + dist = Length(pos, m_impact); + speed = m_impact-pos; + speed.x += (Rand()-0.5f)*dist*1.2f; + speed.y += (Rand()-0.5f)*dist*0.4f+50.0f; + speed.z += (Rand()-0.5f)*dist*1.2f; + dim.x = 1.0f; + dim.y = dim.x; + channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f); + m_particule->SetObjectFather(channel, m_object); + } + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_TERMINATE; +//? m_speed = 1.0f/0.9f; + m_speed = 1.0f/0.4f; + m_progress = 0.0f; +//? m_motion->SetAction(MAS_TERMINATE, 0.9f); + m_motion->SetAction(MAS_TERMINATE, 0.4f); + } + + if ( m_phase == TFA_TERMINATE ) // ends? + { + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_phase = TFA_NULL; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + + Abort(); + return ERR_STOP; +} + + +// Suddenly ends the current action. + +BOOL CTaskFireAnt::Abort() +{ + m_motion->SetAction(-1); + return TRUE; +} + diff --git a/src/object/task/taskfireant.h b/src/object/task/taskfireant.h new file mode 100644 index 0000000..2504241 --- /dev/null +++ b/src/object/task/taskfireant.h @@ -0,0 +1,72 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskfireant.h + +#ifndef _TASKFIREANT_H_ +#define _TASKTIREANT_H_ + + +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskFireAnt +{ + TFA_NULL = 0, // nothing to do + TFA_TURN = 1, // turns + TFA_PREPARE = 2, // prepares shooting position + TFA_FIRE = 3, // shooting + TFA_TERMINATE = 4, // ends shooting position +}; + + + +class CTaskFireAnt : public CTask +{ +public: + CTaskFireAnt(CInstanceManager* iMan, CObject* object); + ~CTaskFireAnt(); + + BOOL EventProcess(const Event &event); + + Error Start(D3DVECTOR impact); + Error IsEnded(); + BOOL Abort(); + +protected: + +protected: + D3DVECTOR m_impact; + TaskFireAnt m_phase; + float m_progress; + float m_speed; + float m_angle; + BOOL m_bError; + BOOL m_bFire; + float m_time; + float m_lastParticule; +}; + + +#endif //_TASKFIREANT_H_ diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp new file mode 100644 index 0000000..b965d08 --- /dev/null +++ b/src/object/task/taskflag.cpp @@ -0,0 +1,321 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskflag.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "pyro.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "motion.h" +#include "motionhuman.h" +#include "sound.h" +#include "task.h" +#include "taskflag.h" + + + + + +// Object's constructor. + +CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskFlag::~CTaskFlag() +{ +} + + +// Management of an event. + +BOOL CTaskFlag::EventProcess(const Event &event) +{ + if ( m_bError ) return TRUE; + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_time += event.rTime; + + return TRUE; +} + + + +// Assigns the goal was achieved. + +Error CTaskFlag::Start(TaskFlagOrder order, int rank) +{ + D3DVECTOR pos, speed; + Error err; + + m_order = order; + m_time = 0.0f; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) + { + pos = m_object->RetPosition(0); + if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER; + return ERR_FLAG_FLY; + } + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_FLAG_MOTOR; + + if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY; + + if ( order == TFL_CREATE ) + { + err = CreateFlag(rank); + if ( err != ERR_OK ) return err; + } + + if ( order == TFL_DELETE ) + { + err = DeleteFlag(); + if ( err != ERR_OK ) return err; + } + + m_bError = FALSE; + + m_motion->SetAction(MHS_FLAG); // sets/removes flag + m_camera->StartCentering(m_object, PI*0.3f, 99.9f, 0.0f, 0.5f); + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskFlag::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) return ERR_STOP; + if ( m_time < 2.0f ) return ERR_CONTINUE; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskFlag::Abort() +{ + m_motion->SetAction(-1); + m_camera->StopCentering(m_object, 2.0f); + return TRUE; +} + + + +// Returns the closest object to a given position. + +CObject* CTaskFlag::SearchNearest(D3DVECTOR pos, ObjectType type) +{ + ObjectType oType; + CObject *pObj, *pBest; + D3DVECTOR oPos; + float min, dist; + int i; + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetEnable() ) continue; + + oType = pObj->RetType(); + if ( type == OBJECT_NULL ) + { + if ( oType != OBJECT_FLAGb && + oType != OBJECT_FLAGr && + oType != OBJECT_FLAGg && + oType != OBJECT_FLAGy && + oType != OBJECT_FLAGv ) continue; + } + else + { + if ( oType != type ) continue; + } + + oPos = pObj->RetPosition(0); + dist = Length2d(oPos, pos); + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + return pBest; +} + +// Counts the number of existing objects. + +int CTaskFlag::CountObject(ObjectType type) +{ + ObjectType oType; + CObject *pObj; + D3DVECTOR oPos; + int i, count; + + count = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetEnable() ) continue; + + oType = pObj->RetType(); + if ( type == OBJECT_NULL ) + { + if ( oType != OBJECT_FLAGb && + oType != OBJECT_FLAGr && + oType != OBJECT_FLAGg && + oType != OBJECT_FLAGy && + oType != OBJECT_FLAGv ) continue; + } + else + { + if ( oType != type ) continue; + } + + count ++; + } + return count; +} + +// Creates a color indicator. + +Error CTaskFlag::CreateFlag(int rank) +{ + CObject* pObj; + CObject* pNew; + CPyro* pyro; + D3DMATRIX* mat; + D3DVECTOR pos; + float dist; + int i; + + ObjectType table[5] = + { + OBJECT_FLAGb, + OBJECT_FLAGr, + OBJECT_FLAGg, + OBJECT_FLAGy, + OBJECT_FLAGv, + }; + + mat = m_object->RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(4.0f, 0.0f, 0.0f)); + + pObj = SearchNearest(pos, OBJECT_NULL); + if ( pObj != 0 ) + { + dist = Length(pos, pObj->RetPosition(0)); + if ( dist < 10.0f ) + { + return ERR_FLAG_PROXY; + } + } + + i = rank; + if ( CountObject(table[i]) >= 5 ) + { + return ERR_FLAG_CREATE; + } + + pNew = new CObject(m_iMan); + if ( !pNew->CreateFlag(pos, 0.0f, table[i]) ) + { + delete pNew; + return ERR_TOOMANY; + } + pNew->SetZoom(0, 0.0f); + + m_sound->Play(SOUND_WAYPOINT, pos); + pyro = new CPyro(m_iMan); + pyro->Create(PT_FLCREATE, pNew); + + return ERR_OK; +} + +// Deletes a color indicator. + +Error CTaskFlag::DeleteFlag() +{ + CObject* pObj; + CPyro* pyro; + D3DVECTOR iPos, oPos; + float iAngle, angle, aLimit, dist; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + pObj = SearchNearest(iPos, OBJECT_NULL); + if ( pObj == 0 ) + { + return ERR_FLAG_DELETE; + } + dist = Length(iPos, pObj->RetPosition(0)); + if ( dist > 10.0f ) + { + return ERR_FLAG_DELETE; + } + + oPos = pObj->RetPosition(0); + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + aLimit = 45.0f*PI/180.0f; + if ( !TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + return ERR_FLAG_DELETE; + } + + m_sound->Play(SOUND_WAYPOINT, iPos); + pyro = new CPyro(m_iMan); + pyro->Create(PT_FLDELETE, pObj); + + return ERR_OK; +} + diff --git a/src/object/task/taskflag.h b/src/object/task/taskflag.h new file mode 100644 index 0000000..aa979f8 --- /dev/null +++ b/src/object/task/taskflag.h @@ -0,0 +1,66 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. +// taskflag.h + +#ifndef _TASKFLAG_H_ +#define _TASKFLAG_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskFlagOrder +{ + TFL_CREATE = 0, // sets + TFL_DELETE = 1, // removes +}; + + + +class CTaskFlag : public CTask +{ +public: + CTaskFlag(CInstanceManager* iMan, CObject* object); + ~CTaskFlag(); + + BOOL EventProcess(const Event &event); + + Error Start(TaskFlagOrder order, int rank); + Error IsEnded(); + BOOL Abort(); + +protected: + Error CreateFlag(int rank); + Error DeleteFlag(); + CObject* SearchNearest(D3DVECTOR pos, ObjectType type); + int CountObject(ObjectType type); + +protected: + TaskFlagOrder m_order; + float m_time; + BOOL m_bError; +}; + + +#endif //_TASKFLAG_H_ diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp new file mode 100644 index 0000000..a6c836f --- /dev/null +++ b/src/object/task/taskgoto.cpp @@ -0,0 +1,2352 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskgoto.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "task.h" +#include "taskgoto.h" + + + +#define FLY_DIST_GROUND 80.0f // minimum distance to remain on the ground +#define FLY_DEF_HEIGHT 50.0f // default flying height +#define BM_DIM_STEP 5.0f + + + + +// Object's constructor. + +CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_bmArray = 0; +} + +// Object's destructor. + +CTaskGoto::~CTaskGoto() +{ + BitmapClose(); +} + + +// Management of an event. + +BOOL CTaskGoto::EventProcess(const Event &event) +{ + D3DVECTOR pos, goal; + FPOINT rot, repulse; + float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir; + Error ret; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + return TRUE; + } + + if ( m_error != ERR_OK ) return FALSE; + + if ( m_bWorm ) + { + WormFrame(event.rTime); + } + + if ( m_phase == TGP_BEAMLEAK ) // leak? + { + m_leakTime += event.rTime; + + pos = m_object->RetPosition(0); + + rot.x = m_leakPos.x-pos.x; + rot.y = m_leakPos.z-pos.z; + dist = Length(rot.x, rot.y); + rot.x /= dist; + rot.y /= dist; + + a = m_object->RetAngleY(0); + g = RotateAngle(rot.x, -rot.y); // CW ! + a = Direction(a, g)*1.0f; + cirSpeed = a; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + a = NormAngle(a); + if ( a > PI*0.5f && a < PI*1.5f ) + { + linSpeed = 1.0f; // obstacle behind -> advance + cirSpeed = -cirSpeed; + } + else + { + linSpeed = -1.0f; // obstacle in front -> back + } + + if ( m_bLeakRecede ) + { + linSpeed = -1.0f; + cirSpeed = 0.0f; + } + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + return TRUE; + } + + if ( m_phase == TGP_BEAMSEARCH ) // search path? + { + if ( m_bmStep == 0 ) + { + // Frees the area around the departure. + BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f); + } + + pos = m_object->RetPosition(0); + + if ( m_bmFretObject == 0 ) + { + goal = m_goal; + dist = 0.0f; + } + else + { + goal = m_goalObject; + dist = TAKE_DIST+2.0f; + if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f; + } + + ret = BeamSearch(pos, goal, dist); + if ( ret == ERR_OK ) + { +#if 0 + D3DVECTOR min, max; + min = pos; + max = m_goal; + if ( min.x > max.x ) Swap(min.x, max.x); + if ( min.z > max.z ) Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD; + else m_phase = TGP_BEAMGOTO; + m_bmIndex = 0; + m_bmWatchDogPos = m_object->RetPosition(0); + m_bmWatchDogTime = 0.0f; + } + if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER ) + { +#if 0 + D3DVECTOR min, max; + min = pos; + max = m_goal; + if ( min.x > max.x ) Swap(min.x, max.x); + if ( min.z > max.z ) Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + m_error = ret; + return FALSE; + } + return TRUE; + } + + if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor? + { + return TRUE; + } + + if ( m_phase == TGP_BEAMUP ) // off? + { + m_physics->SetMotorSpeedY(1.0f); // up + return TRUE; + } + + if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?) + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(FALSE); // there's more + } + + pos = m_object->RetPosition(0); + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f ) + { + if ( m_physics->RetLand() ) + { + m_physics->SetMotorSpeedY(0.0f); + } + else + { + m_physics->SetMotorSpeedY(-1.0f); + } + } + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + goal = m_bmPoints[m_bmIndex]; + goal.y = pos.y; + h = m_terrain->RetFloorHeight(goal, TRUE, TRUE); + dist = Length2d(pos, goal); + if ( dist != 0.0f ) // anticipates? + { + linSpeed = m_physics->RetLinMotionX(MO_REASPEED); + linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED); + goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist; + goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist; + } + goal.y = pos.y; + hh = m_terrain->RetFloorHeight(goal, TRUE, TRUE); + h = Min(h, hh); + linSpeed = 0.0f; + if ( h < m_altitude-1.0f ) + { + linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + } + if ( h > m_altitude+1.0f ) + { + linSpeed = -0.2f; // down + } + m_physics->SetMotorSpeedY(linSpeed); + } + + rot.x = m_bmPoints[m_bmIndex].x-pos.x; + rot.y = m_bmPoints[m_bmIndex].z-pos.z; + dist = Length(rot.x, rot.y); + rot.x /= dist; + rot.y /= dist; + + a = m_object->RetAngleY(0); + g = RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Direction(a, g)*2.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less + + if ( m_bmIndex == m_bmTotal ) // last point? + { + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + } + else + { + linSpeed = 1.0f; // dark without stopping + } + + linSpeed *= 1.0f-(1.0f-0.3f)*Abs(cirSpeed); + +//? if ( dist < 20.0f && Abs(cirSpeed) >= 0.5f ) + if ( Abs(cirSpeed) >= 0.2f ) + { + linSpeed = 0.0f; // turns first, then advance + } + + dist = Length2d(pos, m_bmWatchDogPos); + if ( dist < 1.0f && linSpeed != 0.0f ) + { + m_bmWatchDogTime += event.rTime; + } + else + { + m_bmWatchDogTime = 0.0f; + m_bmWatchDogPos = pos; + } + + if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time? + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamStart(); // we start all + return TRUE; + } + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + return TRUE; + } + + if ( m_phase == TGP_BEAMDOWN ) // landed? + { + m_physics->SetMotorSpeedY(-0.5f); // tomb + return TRUE; + } + + if ( m_phase == TGP_LAND ) // landed? + { + m_physics->SetMotorSpeedY(-0.5f); // tomb + return TRUE; + } + + if ( m_goalMode == TGG_EXPRESS ) + { + if ( m_crashMode == TGC_HALT ) + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(FALSE); // there's more + m_error = ERR_STOP; + return TRUE; + } + } + + pos = m_object->RetPosition(0); + + if ( m_altitude > 0.0f ) + { + h = m_terrain->RetFloorHeight(pos, TRUE, TRUE); + linSpeed = 0.0f; + if ( h < m_altitude ) + { + linSpeed = 0.1f; // up + } + if ( h > m_altitude ) + { + linSpeed = -0.2f; // down + } + m_physics->SetMotorSpeedY(linSpeed); + } + + rot.x = m_goal.x-pos.x; + rot.y = m_goal.z-pos.z; + a = m_object->RetAngleY(0); + g = RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(1.0f); // advance + return TRUE; + } + + if ( m_phase != TGP_TURN && + m_physics->RetType() == TYPE_FLYING && + m_altitude > 0.0f ) + { + pos = m_object->RetPosition(0); + dist = Length2d(m_goal, pos); + factor = (dist-20.0f)/20.0f; + if ( factor < 0.0f ) factor = 0.0f; + if ( factor > 1.0f ) factor = 1.0f; + + h = m_terrain->RetFloorHeight(m_object->RetPosition(0), TRUE, TRUE); + linSpeed = 0.0f; + if ( h < (m_altitude-0.5f)*factor && factor == 1.0f ) + { + linSpeed = 0.1f; // up + } + if ( h > m_altitude*factor ) + { + linSpeed = -0.2f; // down + } + ComputeFlyingRepulse(dir); + linSpeed += dir*0.2f; + + m_physics->SetMotorSpeedY(linSpeed); + } + + if ( m_phase == TGP_ADVANCE ) // going towards the goal? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(FALSE); // there's more + m_time = 0.0f; + m_phase = TGP_CRWAIT; + return TRUE; + } + +#if 0 + pos = m_object->RetPosition(0); + a = m_object->RetAngleY(0); + g = RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW ! + cirSpeed = Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + dist = Length2d(m_goal, pos); + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + + if ( dist < 20.0f && Abs(cirSpeed) >= 0.5f ) + { + linSpeed = 0.0f; // turns first, then advance + } +#else + pos = m_object->RetPosition(0); + + rot.x = m_goal.x-pos.x; + rot.y = m_goal.z-pos.z; + dist = Length(rot.x, rot.y); + rot.x /= dist; + rot.y /= dist; + + ComputeRepulse(repulse); + rot.x += repulse.x*2.0f; + rot.y += repulse.y*2.0f; + + a = m_object->RetAngleY(0); + g = RotateAngle(rot.x, -rot.y); // CW ! + cirSpeed = Direction(a, g)*1.0f; +//? if ( m_physics->RetType() == TYPE_FLYING && +//? m_physics->RetLand() ) // flying on the ground? +//? { +//? cirSpeed *= 4.0f; // more fishing +//? } + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + dist = Length2d(m_goal, pos); + linSpeed = dist/(m_physics->RetLinStopLength()*1.5f); +//? if ( m_physics->RetType() == TYPE_FLYING && +//? m_physics->RetLand() ) // flying on the ground? +//? { +//? linSpeed *= 8.0f; // more fishing +//? } + if ( linSpeed > 1.0f ) linSpeed = 1.0f; + + linSpeed *= 1.0f-(1.0f-0.3f)*Abs(cirSpeed); + + if ( dist < 20.0f && Abs(cirSpeed) >= 0.5f ) + { + linSpeed = 0.0f; // turns first, then advance + } +#endif + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + m_physics->SetMotorSpeedX(linSpeed); // advance + } + + if ( m_phase == TGP_TURN || // turns to the object? + m_phase == TGP_CRTURN || // turns after collision? + m_phase == TGP_CLTURN ) // turns after collision? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + } + + if ( m_phase == TGP_CRWAIT || // waits after collision? + m_phase == TGP_CLWAIT ) // waits after collision? + { + m_time += event.rTime; + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + } + + if ( m_phase == TGP_CRADVANCE ) // advance after collision? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(FALSE); // there's more + m_time = 0.0f; + m_phase = TGP_CLWAIT; + return TRUE; + } + m_physics->SetMotorSpeedX(0.5f); // advance mollo + } + + if ( m_phase == TGP_CLADVANCE ) // advance after collision? + { + if ( m_physics->RetCollision() ) // collision? + { + m_physics->SetCollision(FALSE); // there's more + m_time = 0.0f; + m_phase = TGP_CRWAIT; + return TRUE; + } + m_physics->SetMotorSpeedX(0.5f); // advance mollo + } + + if ( m_phase == TGP_MOVE ) // final advance? + { + m_bmTimeLimit -= event.rTime; + m_physics->SetMotorSpeedX(1.0f); + } + + return TRUE; +} + + +// Sought a target for the worm. + +CObject* CTaskGoto::WormSearch(D3DVECTOR &impact) +{ + CObject* pObj; + CObject* pBest = 0; + D3DVECTOR iPos, oPos; + ObjectType oType; + float distance, min, radius; + int i; + + iPos = m_object->RetPosition(0); + min = 1000000.0f; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + oType = pObj->RetType(); + if ( oType != OBJECT_MOBILEfa && + oType != OBJECT_MOBILEta && + oType != OBJECT_MOBILEwa && + oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfc && + oType != OBJECT_MOBILEtc && + oType != OBJECT_MOBILEwc && + oType != OBJECT_MOBILEic && + oType != OBJECT_MOBILEfi && + oType != OBJECT_MOBILEti && + oType != OBJECT_MOBILEwi && + oType != OBJECT_MOBILEii && + oType != OBJECT_MOBILEfs && + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_MOBILErt && + oType != OBJECT_MOBILErc && + oType != OBJECT_MOBILErr && + oType != OBJECT_MOBILErs && + oType != OBJECT_MOBILEsa && + oType != OBJECT_MOBILEtg && + oType != OBJECT_MOBILEft && + oType != OBJECT_MOBILEtt && + oType != OBJECT_MOBILEwt && + oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILEdr && + oType != OBJECT_DERRICK && + oType != OBJECT_STATION && + oType != OBJECT_FACTORY && + oType != OBJECT_REPAIR && + oType != OBJECT_DESTROYER && + oType != OBJECT_CONVERT && + oType != OBJECT_TOWER && + oType != OBJECT_RESEARCH && + oType != OBJECT_RADAR && + oType != OBJECT_INFO && + oType != OBJECT_ENERGY && + oType != OBJECT_LABO && + oType != OBJECT_NUCLEAR && + oType != OBJECT_PARA && + oType != OBJECT_SAFE && + oType != OBJECT_HUSTON ) continue; + + if ( pObj->RetVirusMode() ) continue; // object infected? + + if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue; + distance = Length2d(oPos, iPos); + if ( distance < min ) + { + min = distance; + pBest = pObj; + } + } + if ( pBest == 0 ) return 0; + + impact = pBest->RetPosition(0); + return pBest; +} + +// Contaminate objects near the worm. + +void CTaskGoto::WormFrame(float rTime) +{ + CObject* pObj; + D3DVECTOR impact, pos; + float dist; + + m_wormLastTime += rTime; + + if ( m_wormLastTime >= 0.5f ) + { + m_wormLastTime = 0.0f; + + pObj = WormSearch(impact); + if ( pObj != 0 ) + { + pos = m_object->RetPosition(0); + dist = Length(pos, impact); + if ( dist <= 15.0f ) + { + pObj->SetVirusMode(TRUE); // bam, infected! + } + } + } +} + + + +// Assigns the goal was achieved. +// "dist" is the distance that needs to go far to make a deposit or object. + +Error CTaskGoto::Start(D3DVECTOR goal, float altitude, + TaskGotoGoal goalMode, TaskGotoCrash crashMode) +{ + D3DVECTOR pos; + CObject* target; + ObjectType type; + float dist; + int x, y; + + type = m_object->RetType(); + + if ( goalMode == TGG_DEFAULT ) + { + goalMode = TGG_STOP; + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_WORM ) + { + goalMode = TGG_EXPRESS; + } + } + + if ( crashMode == TGC_DEFAULT ) + { +//? crashMode = TGC_RIGHTLEFT; + crashMode = TGC_BEAM; + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_WORM || + type == OBJECT_BEE ) + { + crashMode = TGC_HALT; + } + } + + m_altitude = altitude; + m_goalMode = goalMode; + m_crashMode = crashMode; + m_goalObject = goal; + m_goal = goal; + + m_bTake = FALSE; + m_phase = TGP_ADVANCE; + m_error = ERR_OK; + m_try = 0; + m_bmFretObject = 0; + m_bmFinalMove = 0.0f; + + pos = m_object->RetPosition(0); + dist = Length2d(pos, m_goal); + if ( dist < 10.0f && m_crashMode == TGC_BEAM ) + { + m_crashMode = TGC_RIGHTLEFT; + } + + m_bWorm = FALSE; + if ( type == OBJECT_WORM ) + { + m_bWorm = TRUE; + m_wormLastTime = 0.0f; + } + + m_bApprox = FALSE; + if ( type == OBJECT_HUMAN || + type == OBJECT_TECH || + type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) + { + m_bApprox = TRUE; + } + + if ( !m_bApprox && m_crashMode != TGC_BEAM ) + { + target = SearchTarget(goal, 1.0f); + if ( target != 0 ) + { + m_goal = target->RetPosition(0); + dist = 0.0f; + if ( !AdjustBuilding(m_goal, 1.0f, dist) ) + { + dist = 0.0f; + AdjustTarget(target, m_goal, dist); + } + m_bTake = TRUE; // object was taken on arrival (final rotation) + } + } + + m_lastDistance = 1000.0f; + m_physics->SetCollision(FALSE); + + if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays? + { + target = SearchTarget(goal, 1.0f); + if ( target != 0 ) + { + m_goal = target->RetPosition(0); + dist = 4.0f; + if ( AdjustBuilding(m_goal, 1.0f, dist) ) + { + m_bmFinalMove = dist; + } + else + { + dist = 4.0f; + if ( AdjustTarget(target, m_goal, dist) ) + { + m_bmFretObject = target; // cargo on the ground + } + else + { + m_bmFinalMove = dist; + } + } + m_bTake = TRUE; // object was taken on arrival (final rotation) + } + + if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f ) + { + pos = m_object->RetPosition(0); + dist = Length2d(pos, m_goal); + if ( dist > FLY_DIST_GROUND ) // over 20 meters? + { + m_altitude = FLY_DEF_HEIGHT; // default altitude + } + } + + BeamStart(); + + if ( m_bmFretObject == 0 ) + { + x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP); + y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP); + if ( BitmapTestDot(0, x, y) ) // arrival occupied? + { +#if 0 + D3DVECTOR min, max; + min = m_object->RetPosition(0); + max = m_goal; + if ( min.x > max.x ) Swap(min.x, max.x); + if ( min.z > max.z ) Swap(min.z, max.z); + min.x -= 50.0f; + min.z -= 50.0f; + max.x += 50.0f; + max.z += 50.0f; + BitmapDebug(min, max, m_object->RetPosition(0), m_goal); +#endif + m_error = ERR_GOTO_BUSY; + return m_error; + } + } + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskGoto::IsEnded() +{ + D3DVECTOR pos; + float limit, angle, dist, h, level; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_error != ERR_OK ) return m_error; + + pos = m_object->RetPosition(0); + + if ( m_phase == TGP_BEAMLEAK ) // leak? + { + if ( m_leakTime >= m_leakDelay ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamInit(); + m_phase = TGP_BEAMSEARCH; // will seek the path + } + return ERR_CONTINUE; + } + + if ( m_phase == TGP_BEAMSEARCH ) // search path? + { + return ERR_CONTINUE; + } + + if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor? + { + if ( m_altitude != 0.0f && + m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE; + m_phase = TGP_BEAMUP; + } + + if ( m_phase == TGP_BEAMUP ) // off? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + level = m_terrain->RetFloorLevel(pos, TRUE, TRUE); + h = level+m_altitude-20.0f; + limit = m_terrain->RetFlyingMaxHeight(); + if ( h > limit ) h = limit; + if ( pos.y < h-1.0f ) return ERR_CONTINUE; + + m_physics->SetMotorSpeedY(0.0f); // stops the ascent + } + m_phase = TGP_BEAMGOTO; + } + + if ( m_phase == TGP_BEAMGOTO ) // goto dot list ? + { + if ( m_altitude != 0.0f && + m_physics->RetReactorRange() < 0.1f ) // overheating? + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_physics->SetMotorSpeedY(-1.0f); // tomb + m_phase = TGP_BEAMWCOLD; + return ERR_CONTINUE; + } + + if ( m_physics->RetLand() ) // on the ground? + { + limit = 1.0f; + } + else // in flight? + { + limit = 2.0f; + if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point + } + if ( m_bApprox ) limit = 2.0f; + + if ( Abs(pos.x - m_bmPoints[m_bmIndex].x) < limit && + Abs(pos.z - m_bmPoints[m_bmIndex].z) < limit ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + + m_bmIndex = BeamShortcut(); + + if ( m_bmIndex > m_bmTotal ) + { + m_phase = TGP_BEAMDOWN; + } + } + } + + if ( m_phase == TGP_BEAMDOWN ) // landed? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + if ( !m_physics->RetLand() ) return ERR_CONTINUE; + m_physics->SetMotorSpeedY(0.0f); // stops the descent + + m_altitude = 0.0f; + m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish + m_bmIndex = m_bmTotal; + return ERR_CONTINUE; + } + + if ( m_bTake ) + { + m_angle = RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z); + m_phase = TGP_TURN; + } + else + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + return ERR_STOP; + } + } + + if ( m_goalMode == TGG_EXPRESS ) + { + dist = Length2d(m_goal, pos); + if ( dist < 10.0f && dist > m_lastDistance ) + { + return ERR_STOP; + } + m_lastDistance = dist; + } + + if ( m_phase == TGP_ADVANCE ) // going towards the goal? + { + if ( m_physics->RetLand() ) limit = 0.1f; // on the ground + else limit = 1.0f; // flying + if ( m_bApprox ) limit = 2.0f; + + if ( Abs(pos.x - m_goal.x) < limit && + Abs(pos.z - m_goal.z) < limit ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_phase = TGP_LAND; + } + } + + if ( m_phase == TGP_LAND ) // landed? + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + if ( !m_physics->RetLand() ) return ERR_CONTINUE; + m_physics->SetMotorSpeedY(0.0f); + } + + if ( m_bTake ) + { + m_angle = RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z); + m_phase = TGP_TURN; + } + else + { + return ERR_STOP; + } + } + + if ( m_phase == TGP_TURN ) // turns to the object? + { + angle = NormAngle(m_object->RetAngleY(0)); + limit = 0.02f; + if ( m_bApprox ) limit = 0.10f; + if ( Abs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + if ( m_bmFinalMove == 0.0f ) return ERR_STOP; + + m_bmFinalPos = m_object->RetPosition(0); + m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove); + m_bmTimeLimit = m_physics->RetLinTimeLength(Abs(m_bmFinalMove))*1.5f; + if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f; + m_phase = TGP_MOVE; + } + } + + if ( m_phase == TGP_CRWAIT ) // waits after collision? + { + if ( m_crashMode == TGC_HALT ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_error = ERR_GENERIC; + return m_error; + } + if ( m_time >= 1.0f ) + { + if ( m_crashMode == TGC_RIGHTLEFT || + m_crashMode == TGC_RIGHT ) angle = PI/2.0f; // 90 deegres to the right + else angle = -PI/2.0f; // 90 deegres to the left + m_angle = NormAngle(m_object->RetAngleY(0)+angle); + m_phase = TGP_CRTURN; +//? m_phase = TGP_ADVANCE; + } + } + + if ( m_phase == TGP_CRTURN ) // turns after collision? + { + angle = NormAngle(m_object->RetAngleY(0)); + limit = 0.1f; + if ( Abs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_pos = pos; + m_phase = TGP_CRADVANCE; + } + } + + if ( m_phase == TGP_CRADVANCE ) // advance after collision? + { + if ( Length(pos, m_pos) >= 5.0f ) + { + m_phase = TGP_ADVANCE; + } + } + + if ( m_phase == TGP_CLWAIT ) // waits after collision? + { + if ( m_time >= 1.0f ) + { + if ( m_crashMode == TGC_RIGHTLEFT ) angle = -PI; + if ( m_crashMode == TGC_LEFTRIGHT ) angle = PI; + if ( m_crashMode == TGC_RIGHT ) angle = PI/2.0f; + if ( m_crashMode == TGC_LEFT ) angle = -PI/2.0f; + m_angle = NormAngle(m_object->RetAngleY(0)+angle); + m_phase = TGP_CLTURN; + } + } + + if ( m_phase == TGP_CLTURN ) // turns after collision? + { + angle = NormAngle(m_object->RetAngleY(0)); + limit = 0.1f; + if ( Abs(angle-m_angle) < limit ) + { + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_pos = pos; + m_phase = TGP_CLADVANCE; + } + } + + if ( m_phase == TGP_CLADVANCE ) // advance after collision? + { + if ( Length(pos, m_pos) >= 10.0f ) + { + m_phase = TGP_ADVANCE; + m_try ++; + } + } + + if ( m_phase == TGP_MOVE ) // final advance? + { + if ( m_bmTimeLimit <= 0.0f ) + { + m_physics->SetMotorSpeedX(0.0f); // stops + Abort(); + return ERR_STOP; + } + + dist = Length(m_bmFinalPos, m_object->RetPosition(0)); + if ( dist < m_bmFinalDist ) return ERR_CONTINUE; + m_physics->SetMotorSpeedX(0.0f); // stops the advance + return ERR_STOP; + } + + return ERR_CONTINUE; +} + + +// Tries the object is the target position. + +CObject* CTaskGoto::SearchTarget(D3DVECTOR pos, float margin) +{ + CObject *pObj, *pBest; + D3DVECTOR oPos; + float dist, min; + int i; + + pBest = 0; + min = 1000000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transtorted? + + oPos = pObj->RetPosition(0); + dist = Length2d(pos, oPos); + + if ( dist <= margin && dist <= min ) + { + min = dist; + pBest = pObj; + } + } + + return pBest; +} + +// Adjusts the target as a function of the object. +// Returns TRUE if it is cargo laying on the ground, which can be approached from any site. + +BOOL CTaskGoto::AdjustTarget(CObject* pObj, D3DVECTOR &pos, float &distance) +{ + ObjectType type; + Character* character; + D3DMATRIX* mat; + D3DVECTOR goal; + float dist, suppl; + + type = m_object->RetType(); + if ( type == OBJECT_BEE || + type == OBJECT_WORM ) + { + pos = pObj->RetPosition(0); + return FALSE; // single approach + } + + type = pObj->RetType(); + + if ( type == OBJECT_FRET || + type == OBJECT_STONE || + type == OBJECT_URANIUM || + type == OBJECT_METAL || + type == OBJECT_POWER || + type == OBJECT_ATOMIC || + type == OBJECT_BULLET || + type == OBJECT_BBOX || + type == OBJECT_KEYa || + type == OBJECT_KEYb || + type == OBJECT_KEYc || + type == OBJECT_KEYd || + type == OBJECT_TNT || + type == OBJECT_SCRAP1 || + type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 || + type == OBJECT_SCRAP4 || + type == OBJECT_SCRAP5 || + type == OBJECT_BOMB || + type == OBJECT_RUINmobilew1 || + type == OBJECT_RUINmobilew2 || + type == OBJECT_RUINmobilet1 || + type == OBJECT_RUINmobilet2 || + type == OBJECT_RUINmobiler1 || + type == OBJECT_RUINmobiler2 ) + { + pos = m_object->RetPosition(0); + goal = pObj->RetPosition(0); + dist = Length(goal, pos); + pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal; + return TRUE; // approach from all sites + } + + if ( type == OBJECT_BASE ) + { + pos = m_object->RetPosition(0); + goal = pObj->RetPosition(0); + dist = Length(goal, pos); + pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal; + return TRUE; // approach from all sites + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEta || + type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEii || + type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEtg || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEit || + type == OBJECT_MOBILEdr ) + { + character = pObj->RetCharacter(); + pos = character->posPower; + pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance; + mat = pObj->RetWorldMatrix(0); + pos = Transform(*mat, pos); + return FALSE; // single approach + } + + if ( GetHotPoint(pObj, goal, TRUE, distance, suppl) ) + { + pos = goal; + distance += suppl; + return FALSE; // single approach + } + + pos = pObj->RetPosition(0); + distance = 0.0f; + return FALSE; // single approach +} + +// If you are on an object produced by a building (ore produced by derrick), +// changes the position by report the building. + +BOOL CTaskGoto::AdjustBuilding(D3DVECTOR &pos, float margin, float &distance) +{ + CObject* pObj; + D3DVECTOR oPos; + float dist, suppl; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + if ( !GetHotPoint(pObj, oPos, FALSE, 0.0f, suppl) ) continue; + dist = Length2d(pos, oPos); + if ( dist <= margin ) + { + GetHotPoint(pObj, pos, TRUE, distance, suppl); + distance += suppl; + return TRUE; + } + } + return FALSE; +} + +// Returns the item or product or pose is something on a building. + +BOOL CTaskGoto::GetHotPoint(CObject *pObj, D3DVECTOR &pos, + BOOL bTake, float distance, float &suppl) +{ + ObjectType type; + D3DMATRIX* mat; + + pos = D3DVECTOR(0.0f, 0.0f, 0.0f); + suppl = 0.0f; + type = pObj->RetType(); + + if ( type == OBJECT_DERRICK ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 8.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_CONVERT ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 0.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_RESEARCH ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 10.0f; + if ( bTake && distance != 0.0f ) suppl = 2.5f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_ENERGY ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 6.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_TOWER ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 5.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_LABO ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 6.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_NUCLEAR ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 22.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_FACTORY ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 6.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_STATION ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += distance; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_REPAIR ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 4.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += distance; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_DESTROYER ) + { + mat = pObj->RetWorldMatrix(0); + pos.x += 0.0f; + if ( bTake && distance != 0.0f ) suppl = 4.0f; + if ( bTake ) pos.x += TAKE_DIST+distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING ) + { + mat = pObj->RetWorldMatrix(0); + if ( bTake && distance != 0.0f ) suppl = 20.0f; + if ( bTake ) pos.x += distance+suppl; + pos = Transform(*mat, pos); + return TRUE; + } + + suppl = 0.0f; + return FALSE; +} + + +// Seeks an object too close that he must flee. + +BOOL CTaskGoto::LeakSearch(D3DVECTOR &pos, float &delay) +{ + CObject *pObj, *pObstacle; + D3DVECTOR iPos, oPos, bPos; + float iRadius, oRadius, bRadius, dist, min, dir; + int i, j; + + if ( !m_physics->RetLand() ) return FALSE; // in flight? + + m_object->GetCrashSphere(0, iPos, iRadius); + + min = 100000.0f; + bRadius = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + dist = Length2d(oPos, iPos); + if ( dist < min ) + { + min = dist; + bPos = oPos; + bRadius = oRadius; + pObstacle = pObj; + } + } + } + if ( min > iRadius+bRadius+4.0f ) return FALSE; + + m_bLeakRecede = FALSE; + + dist = 4.0f; + dir = 1.0f; + if ( pObstacle->RetType() == OBJECT_FACTORY ) + { + dist = 16.0f; + dir = -1.0f; + m_bLeakRecede = TRUE; // simply recoils + } + + pos = bPos; + delay = m_physics->RetLinTimeLength(dist, dir); + return TRUE; +} + + +// Calculates the force of repulsion due to obstacles. +// The vector length rendered is between 0 and 1. + +void CTaskGoto::ComputeRepulse(FPOINT &dir) +{ +#if 0 + D3DVECTOR iPos, oPos; + FPOINT repulse; + CObject *pObj; + float dist, iRadius, oRadius; + int i; + + dir.x = 0.0f; + dir.y = 0.0f; + + m_object->GetCrashSphere(0, iPos, iRadius); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, m_goalObject); + if ( dist <= 1.0f ) continue; + + pObj->GetGlobalSphere(oPos, oRadius); + oRadius += iRadius+m_physics->RetLinStopLength()*1.1f; + dist = Length2d(oPos, iPos); + if ( dist <= oRadius ) + { + repulse.x = iPos.x-oPos.x; + repulse.y = iPos.z-oPos.z; + +//? dist = 0.2f-(0.2f*dist/oRadius); + dist = powf(dist/oRadius, 2.0f); + dist = 0.2f-0.2f*dist; + repulse.x *= dist; + repulse.y *= dist; +//? repulse.x /= dist; +//? repulse.y /= dist; + + dir.x += repulse.x; + dir.y += repulse.y; + } + } +#else + ObjectType iType, oType; + D3DVECTOR iPos, oPos; + FPOINT repulse; + CObject *pObj; + float gDist, add, addi, fac, dist, iRadius, oRadius; + int i, j; + BOOL bAlien; + + dir.x = 0.0f; + dir.y = 0.0f; + + // The worm goes everywhere and through everything! + iType = m_object->RetType(); + if ( iType == OBJECT_WORM ) return; + + m_object->GetCrashSphere(0, iPos, iRadius); + gDist = Length(iPos, m_goal); + + add = m_physics->RetLinStopLength()*1.1f; // braking distance + fac = 2.0f; + + if ( iType == OBJECT_MOBILEwa || + iType == OBJECT_MOBILEwc || + iType == OBJECT_MOBILEwi || + iType == OBJECT_MOBILEws || + iType == OBJECT_MOBILEwt ) // wheels? + { + add = 5.0f; + fac = 1.5f; + } + if ( iType == OBJECT_MOBILEta || + iType == OBJECT_MOBILEtc || + iType == OBJECT_MOBILEti || + iType == OBJECT_MOBILEts || + iType == OBJECT_MOBILEtt || + iType == OBJECT_MOBILEdr ) // caterpillars? + { + add = 4.0f; + fac = 1.5f; + } + if ( iType == OBJECT_MOBILEfa || + iType == OBJECT_MOBILEfc || + iType == OBJECT_MOBILEfi || + iType == OBJECT_MOBILEfs || + iType == OBJECT_MOBILEft ) // flying? + { + if ( m_physics->RetLand() ) + { + add = 5.0f; + fac = 1.5f; + } + else + { + add = 10.0f; + fac = 1.5f; + } + } + if ( iType == OBJECT_MOBILEia || + iType == OBJECT_MOBILEic || + iType == OBJECT_MOBILEii || + iType == OBJECT_MOBILEis || + iType == OBJECT_MOBILEit ) // legs? + { + add = 4.0f; + fac = 1.5f; + } + if ( iType == OBJECT_BEE ) // wasp? + { + if ( m_physics->RetLand() ) + { + add = 3.0f; + fac = 1.5f; + } + else + { + add = 5.0f; + fac = 1.5f; + } + } + + bAlien = FALSE; + if ( iType == OBJECT_MOTHER || + iType == OBJECT_ANT || + iType == OBJECT_SPIDER || + iType == OBJECT_BEE || + iType == OBJECT_WORM ) + { + bAlien = TRUE; + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oType = pObj->RetType(); + + if ( oType == OBJECT_WORM ) continue; + + if ( bAlien ) + { + if ( oType == OBJECT_STONE || + oType == OBJECT_URANIUM || + oType == OBJECT_METAL || + oType == OBJECT_POWER || + oType == OBJECT_ATOMIC || + oType == OBJECT_BULLET || + oType == OBJECT_BBOX || + oType == OBJECT_KEYa || + oType == OBJECT_KEYb || + oType == OBJECT_KEYc || + oType == OBJECT_KEYd || + oType == OBJECT_TNT || + oType == OBJECT_SCRAP1 || + oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 || + oType == OBJECT_BOMB || + (oType >= OBJECT_PLANT0 && + oType <= OBJECT_PLANT19 ) || + (oType >= OBJECT_MUSHROOM0 && + oType <= OBJECT_MUSHROOM9 ) ) continue; + } + + addi = add; + if ( iType == OBJECT_BEE && + oType == OBJECT_BEE ) + { + addi = 2.0f; // between wasps, do not annoy too much + } + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( oPos.y-oRadius > iPos.y+iRadius ) continue; + if ( oPos.y+oRadius < iPos.y-iRadius ) continue; + + dist = Length(oPos, m_goal); + if ( dist <= 1.0f ) continue; // on purpose? + + oRadius += iRadius+addi; + dist = Length2d(oPos, iPos); + if ( dist > gDist ) continue; // beyond the goal? + if ( dist <= oRadius ) + { + repulse.x = iPos.x-oPos.x; + repulse.y = iPos.z-oPos.z; + + dist = powf(dist/oRadius, fac); + dist = 0.2f-0.2f*dist; + repulse.x *= dist; + repulse.y *= dist; + + dir.x += repulse.x; + dir.y += repulse.y; + } + } + } +#endif +} + +// Calculates the force of vertical repulsion according to barriers. +// The vector length is made​between -1 and 1. + +void CTaskGoto::ComputeFlyingRepulse(float &dir) +{ + ObjectType oType; + D3DVECTOR iPos, oPos; + CObject *pObj; + float add, fac, dist, iRadius, oRadius, repulse; + int i, j; + + m_object->GetCrashSphere(0, iPos, iRadius); + + add = 0.0f; + fac = 1.5f; + dir = 0.0f; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + oType = pObj->RetType(); + + if ( oType == OBJECT_WORM ) continue; + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + oRadius += iRadius+add; + dist = Length2d(oPos, iPos); + if ( dist <= oRadius ) + { + repulse = iPos.y-oPos.y; + + dist = powf(dist/oRadius, fac); + dist = 0.2f-0.2f*dist; + repulse *= dist; + + dir += repulse; + } + } + } + + if ( dir < -1.0f ) dir = -1.0f; + if ( dir > 1.0f ) dir = 1.0f; +} + + + +// Among all of the following, seek if there is one allowing to go directly to the crow flies. +// If yes, skip all the unnecessary intermediate points. + +int CTaskGoto::BeamShortcut() +{ + int i; + + for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last + { + if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, FALSE) ) + { + return i; // bingo, found + } + } + + return m_bmIndex+1; // simply goes to the next +} + +// That's the big start. + +void CTaskGoto::BeamStart() +{ + D3DVECTOR min, max; + + BitmapOpen(); + BitmapObject(); + + min = m_object->RetPosition(0); + max = m_goal; + if ( min.x > max.x ) Swap(min.x, max.x); + if ( min.z > max.z ) Swap(min.z, max.z); + min.x -= 10.0f*BM_DIM_STEP; + min.z -= 10.0f*BM_DIM_STEP; + max.x += 10.0f*BM_DIM_STEP; + max.z += 10.0f*BM_DIM_STEP; + BitmapTerrain(min, max); + + if ( LeakSearch(m_leakPos, m_leakDelay) ) + { + m_phase = TGP_BEAMLEAK; // must first leak + m_leakTime = 0.0f; + } + else + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + BeamInit(); + m_phase = TGP_BEAMSEARCH; // will seek the path + } +} + +// Initialization before the first BeamSearch. + +void CTaskGoto::BeamInit() +{ + int i; + + for ( i=0 ; i 20.0f ) step = 20.0f; + nbIter = 200; // in order not to lower the framerate + m_bmIterCounter = 0; + return BeamExplore(start, start, goal, goalRadius, 165.0f*PI/180.0f, 22, step, 0, nbIter); +} + +// prevPos: previous position +// curPos: current position +// goalPos: position that seeks to achieve +// angle: angle to the goal we explores +// nbDiv: number of subdivisions being done with angle +// step length of a step +// i number of recursions made +// nbIter maximum number of iterations you have the right to make before temporarily interrupt + +Error CTaskGoto::BeamExplore(const D3DVECTOR &prevPos, const D3DVECTOR &curPos, + const D3DVECTOR &goalPos, float goalRadius, + float angle, int nbDiv, float step, + int i, int nbIter) +{ + D3DVECTOR newPos; + Error ret; + int iDiv, iClear, iLar; + + iLar = 0; + if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions + + if ( m_bmIter[i] == -1 ) + { + m_bmIter[i] = 0; + + if ( i == 0 ) + { + m_bmPoints[i] = curPos; + } + else + { + if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, TRUE) ) return ERR_GOTO_IMPOSSIBLE; + + m_bmPoints[i] = curPos; + + if ( Length2d(curPos, goalPos)-goalRadius <= step ) + { + if ( goalRadius == 0.0f ) + { + newPos = goalPos; + } + else + { + newPos = BeamPoint(curPos, goalPos, 0, Length2d(curPos, goalPos)-goalRadius); + } + if ( BitmapTestLine(curPos, newPos, angle/nbDiv, FALSE) ) + { + m_bmPoints[i+1] = newPos; + m_bmTotal = i+1; + return ERR_OK; + } + } + } + } + + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, 0, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + + for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ ) + { + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + + if ( iLar >= m_bmIter[i] ) + { + newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step); + ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter); + if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret; + m_bmIter[i] = iLar+1; + for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1; + m_bmIterCounter ++; + if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE; + } + iLar ++; + } + + return ERR_GOTO_IMPOSSIBLE; +} + +// Is a right "start-goal". Calculates the point located at the distance "step" +// from the point "start" and an angle "angle" with the right. + +D3DVECTOR CTaskGoto::BeamPoint(const D3DVECTOR &startPoint, + const D3DVECTOR &goalPoint, + float angle, float step) +{ + D3DVECTOR resPoint; + float goalAngle; + + goalAngle = RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z); + + resPoint.x = startPoint.x + cosf(goalAngle+angle)*step; + resPoint.z = startPoint.z + sinf(goalAngle+angle)*step; + resPoint.y = 0.0f; + + return resPoint; +} + +// Displays a bitmap part. + +void CTaskGoto::BitmapDebug(const D3DVECTOR &min, const D3DVECTOR &max, + const D3DVECTOR &start, const D3DVECTOR &goal) +{ + int minx, miny, maxx, maxy, x, y, i ,n; + char s[2000]; + + minx = (int)((min.x+1600.0f)/BM_DIM_STEP); + miny = (int)((min.z+1600.0f)/BM_DIM_STEP); + maxx = (int)((max.x+1600.0f)/BM_DIM_STEP); + maxy = (int)((max.z+1600.0f)/BM_DIM_STEP); + + if ( minx > maxx ) Swap(minx, maxx); + if ( miny > maxy ) Swap(miny, maxy); + + OutputDebugString("Bitmap :\n"); + for ( y=miny ; y<=maxy ; y++ ) + { + s[0] = 0; + for ( x=minx ; x<=maxx ; x++ ) + { + n = -1; + for ( i=0 ; i<=m_bmTotal ; i++ ) + { + if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) && + y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) ) + { + n = i; + break; + } + } + + if ( BitmapTestDot(0, x,y) ) + { + strcat(s, "o"); + } + else + { + if ( BitmapTestDot(1, x,y) ) + { + strcat(s, "-"); + } + else + { + strcat(s, "."); + } + } + + if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) && + y == (int)((start.z+1600.0f)/BM_DIM_STEP) ) + { + strcat(s, "s"); + } + else + if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) && + y == (int)((goal.z+1600.0f)/BM_DIM_STEP) ) + { + strcat(s, "g"); + } + else + if ( n != -1 ) + { + char ss[2]; + ss[0] = 'A'+n; + ss[1] = 0; + strcat(s, ss); + } + else + { + strcat(s, " "); + } + } + strcat(s, "\n"); + OutputDebugString(s); + } +} + +// Tests if a path along a straight line is possible. + +BOOL CTaskGoto::BitmapTestLine(const D3DVECTOR &start, const D3DVECTOR &goal, + float stepAngle, BOOL bSecond) +{ + D3DVECTOR pos, inc; + float dist, step; + float distNoB2; + int i, max, x, y; + + if ( m_bmArray == 0 ) return TRUE; + + dist = Length2d(start, goal); + if ( dist == 0.0f ) return TRUE; + step = BM_DIM_STEP*0.5f; + + inc.x = (goal.x-start.x)*step/dist; + inc.z = (goal.z-start.z)*step/dist; + + pos = start; + + if ( bSecond ) + { + x = (int)((pos.x+1600.0f)/BM_DIM_STEP); + y = (int)((pos.z+1600.0f)/BM_DIM_STEP); + BitmapSetDot(1, x, y); // puts the flag as the starting point + } + + max = (int)(dist/step); + if ( max == 0 ) max = 1; + distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle); + for ( i=0 ; i 2 && BitmapTestDot(1, x, y) ) return FALSE; + + if ( step*(i+1) > distNoB2 && i < max-2 ) + { + BitmapSetDot(1, x, y); + } + } + + if ( BitmapTestDot(0, x, y) ) return FALSE; + } + return TRUE; +} + +// Adds the objects in the bitmap. + +void CTaskGoto::BitmapObject() +{ + CObject *pObj; + ObjectType type; + D3DVECTOR iPos, oPos; + float iRadius, oRadius, h; + int i, j; + + m_object->GetCrashSphere(0, iPos, iRadius); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( pObj == m_object ) continue; + if ( pObj == m_bmFretObject ) continue; + if ( pObj->RetTruck() != 0 ) continue; + + h = m_terrain->RetFloorLevel(pObj->RetPosition(0), FALSE); + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) + { + h += m_altitude; + } + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying? + { + if ( oPos.y-oRadius > h+8.0f || + oPos.y+oRadius < h-8.0f ) continue; + } + else // crawling? + { + if ( oPos.y-oRadius > h+8.0f ) continue; + } + + if ( type == OBJECT_PARA ) oRadius -= 2.0f; + BitmapSetCircle(oPos, oRadius+iRadius+4.0f); + } + } +} + +// Adds a section of land in the bitmap. + +void CTaskGoto::BitmapTerrain(const D3DVECTOR &min, const D3DVECTOR &max) +{ + int minx, miny, maxx, maxy; + + minx = (int)((min.x+1600.0f)/BM_DIM_STEP); + miny = (int)((min.z+1600.0f)/BM_DIM_STEP); + maxx = (int)((max.x+1600.0f)/BM_DIM_STEP); + maxy = (int)((max.z+1600.0f)/BM_DIM_STEP); + + BitmapTerrain(minx, miny, maxx, maxy); +} + +// Adds a section of land in the bitmap. + +void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) +{ + ObjectType type; + D3DVECTOR p; + float aLimit, angle, h; + int x, y; + BOOL bAcceptWater, bFly; + + if ( minx > maxx ) Swap(minx, maxx); + if ( miny > maxy ) Swap(miny, maxy); + + if ( minx < 0 ) minx = 0; + if ( miny < 0 ) miny = 0; + if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1; + if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1; + + if ( minx > m_bmMinX ) minx = m_bmMinX; + if ( miny > m_bmMinY ) miny = m_bmMinY; + if ( maxx < m_bmMaxX ) maxx = m_bmMaxX; + if ( maxy < m_bmMaxY ) maxy = m_bmMaxY; + + if ( minx >= m_bmMinX && maxx <= m_bmMaxX && + miny >= m_bmMinY && maxy <= m_bmMaxY ) return; + + aLimit = 20.0f*PI/180.0f; + bAcceptWater = FALSE; + bFly = FALSE; + + type = m_object->RetType(); + + if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwc || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEwi || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEtg ) // wheels? + { + aLimit = 20.0f*PI/180.0f; + } + + if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtc || + type == OBJECT_MOBILEti || + type == OBJECT_MOBILEts ) // caterpillars? + { + aLimit = 35.0f*PI/180.0f; + } + + if ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs ) // large caterpillars? + { + aLimit = 35.0f*PI/180.0f; + } + + if ( type == OBJECT_MOBILEsa ) // submarine caterpillars? + { + aLimit = 35.0f*PI/180.0f; + bAcceptWater = TRUE; + } + + if ( type == OBJECT_MOBILEdr ) // designer caterpillars? + { + aLimit = 35.0f*PI/180.0f; + } + + if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfc || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEfi || + type == OBJECT_MOBILEft ) // flying? + { + aLimit = 15.0f*PI/180.0f; + bFly = TRUE; + } + + if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEic || + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEii ) // insect legs? + { + aLimit = 60.0f*PI/180.0f; + } + + for ( y=miny ; y<=maxy ; y++ ) + { + for ( x=minx ; x<=maxx ; x++ ) + { + if ( x >= m_bmMinX && x <= m_bmMaxX && + y >= m_bmMinY && y <= m_bmMaxY ) continue; + + p.x = x*BM_DIM_STEP-1600.0f; + p.z = y*BM_DIM_STEP-1600.0f; + + if ( bFly ) // flying robot? + { + h = m_terrain->RetFloorLevel(p, TRUE); + if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f ) + { + BitmapSetDot(0, x, y); + } + continue; + } + + if ( !bAcceptWater ) // not going underwater? + { + h = m_terrain->RetFloorLevel(p, TRUE); + if ( h < m_water->RetLevel()-2.0f ) // under water (*)? + { +//? BitmapSetDot(0, x, y); + BitmapSetCircle(p, BM_DIM_STEP*1.0f); + continue; + } + } + + angle = m_terrain->RetFineSlope(p); + if ( angle > aLimit ) + { + BitmapSetDot(0, x, y); + } + } + } + + m_bmMinX = minx; + m_bmMinY = miny; + m_bmMaxX = maxx; + m_bmMaxY = maxy; // expanded rectangular area +} + +// (*) Accepts that a robot is 50cm under water, for example Tropica 3! + +// Opens an empty bitmap. + +BOOL CTaskGoto::BitmapOpen() +{ + BitmapClose(); + + m_bmSize = (int)(3200.0f/BM_DIM_STEP); + m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2); + ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2); + + m_bmOffset = m_bmSize/2; + m_bmLine = m_bmSize/8; + + m_bmMinX = m_bmSize; // non-existent rectangular area + m_bmMinY = m_bmSize; + m_bmMaxX = 0; + m_bmMaxY = 0; + + return TRUE; +} + +// Closes the bitmap. + +BOOL CTaskGoto::BitmapClose() +{ + free(m_bmArray); + m_bmArray = 0; + return TRUE; +} + +// Puts a circle in the bitmap. + +void CTaskGoto::BitmapSetCircle(const D3DVECTOR &pos, float radius) +{ + float d, r; + int cx, cy, ix, iy; + + cx = (int)((pos.x+1600.0f)/BM_DIM_STEP); + cy = (int)((pos.z+1600.0f)/BM_DIM_STEP); + r = radius/BM_DIM_STEP; + + for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ ) + { + for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ ) + { + d = Length((float)(ix-cx), (float)(iy-cy)); + if ( d > r ) continue; + BitmapSetDot(0, ix, iy); + } + } +} + +// Removes a circle in the bitmap. + +void CTaskGoto::BitmapClearCircle(const D3DVECTOR &pos, float radius) +{ + float d, r; + int cx, cy, ix, iy; + + cx = (int)((pos.x+1600.0f)/BM_DIM_STEP); + cy = (int)((pos.z+1600.0f)/BM_DIM_STEP); + r = radius/BM_DIM_STEP; + + for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ ) + { + for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ ) + { + d = Length((float)(ix-cx), (float)(iy-cy)); + if ( d > r ) continue; + BitmapClearDot(0, ix, iy); + } + } +} + +// Makes a point in the bitmap. +// x:y: 0..m_bmSize-1 + +void CTaskGoto::BitmapSetDot(int rank, int x, int y) +{ + if ( x < 0 || x >= m_bmSize || + y < 0 || y >= m_bmSize ) return; + + m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<= m_bmSize || + y < 0 || y >= m_bmSize ) return; + + m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<= m_bmSize || + y < 0 || y >= m_bmSize ) return FALSE; + + if ( x < m_bmMinX || x > m_bmMaxX || + y < m_bmMinY || y > m_bmMaxY ) + { + BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer + } + + return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1< +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "object.h" +#include "sound.h" +#include "task.h" +#include "taskgungoal.h" + + + + +// Object's constructor. + +CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskGunGoal::~CTaskGunGoal() +{ +} + + +// Management of an event. + +BOOL CTaskGunGoal::EventProcess(const Event &event) +{ + float dir; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_progress += event.rTime*m_speed; + + if ( m_progress < 1.0f ) + { + dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress; + } + else + { + dir = m_finalDirV; + } + m_object->SetGunGoalV(dir); + + if ( m_progress < 1.0f ) + { + dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress; + } + else + { + dir = m_finalDirH; + } + m_object->SetGunGoalH(dir); + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskGunGoal::Start(float dirV, float dirH) +{ + float speedV, speedH; + int i; + + m_initialDirV = m_object->RetGunGoalV(); + m_object->SetGunGoalV(dirV); + m_finalDirV = m_object->RetGunGoalV(); // possible direction + m_object->SetGunGoalV(m_initialDirV); // gives initial direction + + if ( m_finalDirV == m_initialDirV ) + { + speedV = 100.0f; + } + else + { + speedV = 1.0f/(Abs(m_finalDirV-m_initialDirV)*1.0f); + } + + m_initialDirH = m_object->RetGunGoalH(); + m_object->SetGunGoalH(dirH); + m_finalDirH = m_object->RetGunGoalH(); // possible direction + m_object->SetGunGoalH(m_initialDirH); // gives initial direction + + if ( m_finalDirH == m_initialDirH ) + { + speedH = 100.0f; + } + else + { + speedH = 1.0f/(Abs(m_finalDirH-m_initialDirH)*1.0f); + } + + m_speed = Min(speedV, speedH); + + if ( m_finalDirV != m_initialDirV || + m_finalDirH != m_initialDirH ) + { + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, TRUE); + m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP); + } + + m_progress = 0.0f; + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskGunGoal::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_initialDirV == m_finalDirV && + m_initialDirH == m_finalDirH ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + m_object->SetGunGoalV(m_finalDirV); + m_object->SetGunGoalH(m_finalDirH); + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskGunGoal::Abort() +{ + return TRUE; +} + diff --git a/src/object/task/taskgungoal.h b/src/object/task/taskgungoal.h new file mode 100644 index 0000000..4b6cbc7 --- /dev/null +++ b/src/object/task/taskgungoal.h @@ -0,0 +1,57 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskgungoal.h + +#ifndef _TASKGUNGOAL_H_ +#define _TASKGUNGOAL_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskGunGoal : public CTask +{ +public: + CTaskGunGoal(CInstanceManager* iMan, CObject* object); + ~CTaskGunGoal(); + + BOOL EventProcess(const Event &event); + + Error Start(float dirV, float dirH); + Error IsEnded(); + BOOL Abort(); + +protected: + +protected: + float m_progress; + float m_speed; + float m_initialDirV; // initial direction + float m_finalDirV; // direction to reach + float m_initialDirH; // initial direction + float m_finalDirH; // direction to reach +}; + + +#endif //_TASKGUNGOAL_H_ diff --git a/src/object/task/taskinfo.cpp b/src/object/task/taskinfo.cpp new file mode 100644 index 0000000..51deb79 --- /dev/null +++ b/src/object/task/taskinfo.cpp @@ -0,0 +1,233 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskinfo.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "sound.h" +#include "auto.h" +#include "autoinfo.h" +#include "task.h" +#include "taskinfo.h" + + + + +// Object's constructor. + +CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskInfo::~CTaskInfo() +{ +} + + +// Management of an event. + +BOOL CTaskInfo::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_progress += event.rTime*m_speed; // other advance + m_time += event.rTime; + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskInfo::Start(char *name, float value, float power, BOOL bSend) +{ + CObject* pInfo; + CAutoInfo* pAuto; + D3DVECTOR pos, goal; + Info info; + int i, total, op; + + m_bError = TRUE; + m_object->SetInfoReturn(NAN); + + pInfo = SearchInfo(power); // seeks terminal + if ( pInfo == 0 ) + { + return ERR_INFO_NULL; + } + + pAuto = (CAutoInfo*)pInfo->RetAuto(); + if ( pAuto == 0 ) + { + return ERR_INFO_NULL; + } + + op = 1; // transmission impossible + if ( bSend ) // send? + { + total = pInfo->RetInfoTotal(); + for ( i=0 ; iRetInfo(i); + if ( strcmp(info.name, name) == 0 ) + { + info.value = value; + pInfo->SetInfo(i, info); + break; + } + } + if ( i == total ) + { + if ( total < OBJECTMAXINFO ) + { + strcpy(info.name, name); + info.value = value; + pInfo->SetInfo(total, info); + op = 2; // start of reception (for terminal) + } + } + else + { + op = 2; // start of reception (for terminal) + } + } + else // receive? + { + total = pInfo->RetInfoTotal(); + for ( i=0 ; iRetInfo(i); + if ( strcmp(info.name, name) == 0 ) + { + m_object->SetInfoReturn(info.value); + break; + } + } + if ( i < total ) + { + op = 0; // beginning of transmission (for terminal) + } + } + + pAuto->Start(op); + + if ( op == 0 ) // transmission? + { + pos = pInfo->RetPosition(0); + pos.y += 9.5f; + goal = m_object->RetPosition(0); + goal.y += 4.0f; + m_particule->CreateRay(pos, goal, PARTIRAY3, FPOINT(2.0f, 2.0f), 1.0f); + } + if ( op == 2 ) // reception? + { + goal = pInfo->RetPosition(0); + goal.y += 9.5f; + pos = m_object->RetPosition(0); + pos.y += 4.0f; + m_particule->CreateRay(pos, goal, PARTIRAY3, FPOINT(2.0f, 2.0f), 1.0f); + } + + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + + m_bError = FALSE; // ok + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskInfo::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskInfo::Abort() +{ + return TRUE; +} + + +// Seeks the nearest information terminal. + +CObject* CTaskInfo::SearchInfo(float power) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float dist, min; + int i; + + iPos = m_object->RetPosition(0); + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_INFO ) continue; + + if ( !pObj->RetActif() ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, iPos); + if ( dist > power ) continue; // too far? + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + + return pBest; +} + diff --git a/src/object/task/taskinfo.h b/src/object/task/taskinfo.h new file mode 100644 index 0000000..26b2071 --- /dev/null +++ b/src/object/task/taskinfo.h @@ -0,0 +1,57 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskinfo.h + +#ifndef _TASKINFO_H_ +#define _TASKINFO_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +class CTaskInfo : public CTask +{ +public: + CTaskInfo(CInstanceManager* iMan, CObject* object); + ~CTaskInfo(); + + BOOL EventProcess(const Event &event); + + Error Start(char *name, float value, float power, BOOL bSend); + Error IsEnded(); + BOOL Abort(); + +protected: + CObject* SearchInfo(float power); + +protected: + float m_progress; + float m_speed; + float m_time; + BOOL m_bError; +}; + + +#endif //_TASKINFO_H_ diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp new file mode 100644 index 0000000..ffc0d05 --- /dev/null +++ b/src/object/task/taskmanager.cpp @@ -0,0 +1,291 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskmanager.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "misc.h" +#include "iman.h" +#include "event.h" +#include "object.h" +#include "task.h" +#include "taskwait.h" +#include "taskadvance.h" +#include "taskturn.h" +#include "taskgoto.h" +#include "tasktake.h" +#include "taskmanip.h" +#include "taskflag.h" +#include "taskbuild.h" +#include "tasksearch.h" +#include "taskterraform.h" +#include "taskpen.h" +#include "taskrecover.h" +#include "taskshield.h" +#include "taskinfo.h" +#include "taskfire.h" +#include "taskfireant.h" +#include "taskgungoal.h" +#include "taskspiderexplo.h" +#include "taskreset.h" +#include "taskmanager.h" + + + + +// Object's constructor. + +CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100); + + m_task = 0; + m_object = object; + m_bPilot = FALSE; +} + +// Object's destructor. + +CTaskManager::~CTaskManager() +{ + delete m_task; +} + + + +// Waits for a while. + +Error CTaskManager::StartTaskWait(float time) +{ + m_task = new CTaskWait(m_iMan, m_object); + return ((CTaskWait*)m_task)->Start(time); +} + +// Advance straight ahead a certain distance. + +Error CTaskManager::StartTaskAdvance(float length) +{ + m_task = new CTaskAdvance(m_iMan, m_object); + return ((CTaskAdvance*)m_task)->Start(length); +} + +// Turns through an certain angle. + +Error CTaskManager::StartTaskTurn(float angle) +{ + m_task = new CTaskTurn(m_iMan, m_object); + return ((CTaskTurn*)m_task)->Start(angle); +} + +// Reaches a given position. + +Error CTaskManager::StartTaskGoto(D3DVECTOR pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode) +{ + m_task = new CTaskGoto(m_iMan, m_object); + return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode); +} + +// Move the manipulator arm. + +Error CTaskManager::StartTaskTake() +{ + m_task = new CTaskTake(m_iMan, m_object); + return ((CTaskTake*)m_task)->Start(); +} + +// Move the manipulator arm. + +Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm) +{ + m_task = new CTaskManip(m_iMan, m_object); + return ((CTaskManip*)m_task)->Start(order, arm); +} + +// Puts or removes a flag. + +Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank) +{ + m_task = new CTaskFlag(m_iMan, m_object); + return ((CTaskFlag*)m_task)->Start(order, rank); +} + +// Builds a building. + +Error CTaskManager::StartTaskBuild(ObjectType type) +{ + m_task = new CTaskBuild(m_iMan, m_object); + return ((CTaskBuild*)m_task)->Start(type); +} + +// Probe the ground. + +Error CTaskManager::StartTaskSearch() +{ + m_task = new CTaskSearch(m_iMan, m_object); + return ((CTaskSearch*)m_task)->Start(); +} + +// Reads an information terminal. + +Error CTaskManager::StartTaskInfo(char *name, float value, float power, BOOL bSend) +{ + m_task = new CTaskInfo(m_iMan, m_object); + return ((CTaskInfo*)m_task)->Start(name, value, power, bSend); +} + +// Terraforms the ground. + +Error CTaskManager::StartTaskTerraform() +{ + m_task = new CTaskTerraform(m_iMan, m_object); + return ((CTaskTerraform*)m_task)->Start(); +} + +// Changes the pencil. + +Error CTaskManager::StartTaskPen(BOOL bDown, int color) +{ + m_task = new CTaskPen(m_iMan, m_object); + return ((CTaskPen*)m_task)->Start(bDown, color); +} + +// Recovers a ruin. + +Error CTaskManager::StartTaskRecover() +{ + m_task = new CTaskRecover(m_iMan, m_object); + return ((CTaskRecover*)m_task)->Start(); +} + +// Deploys the shield. + +Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay) +{ + if ( mode == TSM_UP ) + { + m_task = new CTaskShield(m_iMan, m_object); + return ((CTaskShield*)m_task)->Start(mode, delay); + } + if ( mode == TSM_DOWN && m_task != 0 ) + { + return ((CTaskShield*)m_task)->Start(mode, delay); + } + if ( mode == TSM_UPDATE && m_task != 0 ) + { + return ((CTaskShield*)m_task)->Start(mode, delay); + } + return ERR_GENERIC; +} + +// Shoots. + +Error CTaskManager::StartTaskFire(float delay) +{ + m_bPilot = TRUE; + m_task = new CTaskFire(m_iMan, m_object); + return ((CTaskFire*)m_task)->Start(delay); +} + +// Shoots with the ant. + +Error CTaskManager::StartTaskFireAnt(D3DVECTOR impact) +{ + m_task = new CTaskFireAnt(m_iMan, m_object); + return ((CTaskFireAnt*)m_task)->Start(impact); +} + +// Adjusts higher. + +Error CTaskManager::StartTaskGunGoal(float dirV, float dirH) +{ + m_task = new CTaskGunGoal(m_iMan, m_object); + return ((CTaskGunGoal*)m_task)->Start(dirV, dirH); +} + +// Suicide of the spider. + +Error CTaskManager::StartTaskSpiderExplo() +{ + m_task = new CTaskSpiderExplo(m_iMan, m_object); + return ((CTaskSpiderExplo*)m_task)->Start(); +} + +// Reset. + +Error CTaskManager::StartTaskReset(D3DVECTOR goal, D3DVECTOR angle) +{ + m_task = new CTaskReset(m_iMan, m_object); + return ((CTaskReset*)m_task)->Start(goal, angle); +} + + + + + +// Management of an event. + +BOOL CTaskManager::EventProcess(const Event &event) +{ + if ( m_task == 0 ) return FALSE; + return m_task->EventProcess(event); +} + + +// Indicates whether the action is finished. + +Error CTaskManager::IsEnded() +{ + if ( m_task == 0 ) return ERR_GENERIC; + return m_task->IsEnded(); +} + + +// Indicates whether the action is pending. + +BOOL CTaskManager::IsBusy() +{ + if ( m_task == 0 ) return FALSE; + return m_task->IsBusy(); +} + + +// Indicates whether it is possible to control the robot +// during the execution of the current task. + +BOOL CTaskManager::IsPilot() +{ + return m_bPilot; +} + + +// Suddenly ends the current action. + +BOOL CTaskManager::Abort() +{ + if ( m_task == 0 ) return FALSE; + return m_task->Abort(); +} + + diff --git a/src/object/task/taskmanager.h b/src/object/task/taskmanager.h new file mode 100644 index 0000000..2c6c21f --- /dev/null +++ b/src/object/task/taskmanager.h @@ -0,0 +1,77 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskmanager.h + +#ifndef _TASKMANAGER_H_ +#define _TASKMANAGER_H_ + +#include "misc.h" +#include "object.h" +#include "taskmanip.h" +#include "taskgoto.h" +#include "taskshield.h" +#include "taskflag.h" + + +class CInstanceManager; +class CTask; + + + +class CTaskManager +{ +public: + CTaskManager(CInstanceManager* iMan, CObject* object); + ~CTaskManager(); + + Error StartTaskWait(float time); + Error StartTaskAdvance(float length); + Error StartTaskTurn(float angle); + Error StartTaskGoto(D3DVECTOR pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode); + Error StartTaskTake(); + Error StartTaskManip(TaskManipOrder order, TaskManipArm arm); + Error StartTaskFlag(TaskFlagOrder order, int rank); + Error StartTaskBuild(ObjectType type); + Error StartTaskSearch(); + Error StartTaskInfo(char *name, float value, float power, BOOL bSend); + Error StartTaskTerraform(); + Error StartTaskPen(BOOL bDown, int color); + Error StartTaskRecover(); + Error StartTaskShield(TaskShieldMode mode, float delay); + Error StartTaskFire(float delay); + Error StartTaskFireAnt(D3DVECTOR impact); + Error StartTaskGunGoal(float dirV, float dirH); + Error StartTaskSpiderExplo(); + Error StartTaskReset(D3DVECTOR goal, D3DVECTOR angle); + + BOOL EventProcess(const Event &event); + Error IsEnded(); + BOOL IsBusy(); + BOOL IsPilot(); + BOOL Abort(); + +protected: + +protected: + CInstanceManager* m_iMan; + CTask* m_task; + CObject* m_object; + BOOL m_bPilot; +}; + + +#endif //_TASKMANAGER_H_ diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp new file mode 100644 index 0000000..672b96e --- /dev/null +++ b/src/object/task/taskmanip.cpp @@ -0,0 +1,1398 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskmanip.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "object.h" +#include "pyro.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "robotmain.h" +#include "task.h" +#include "taskmanip.h" + + +//?#define MARGIN_FRONT 2.0f +//?#define MARGIN_BACK 2.0f +//?#define MARGIN_FRIEND 2.0f +//?#define MARGIN_BEE 5.0f +#define MARGIN_FRONT 4.0f //OK 1.9 +#define MARGIN_BACK 4.0f //OK 1.9 +#define MARGIN_FRIEND 4.0f //OK 1.9 +#define MARGIN_BEE 5.0f //OK 1.9 + + + + +// Object's constructor. + +CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_arm = TMA_NEUTRAL; + m_hand = TMH_OPEN; +} + +// Object's destructor. + +CTaskManip::~CTaskManip() +{ +} + + +// Management of an event. + +BOOL CTaskManip::EventProcess(const Event &event) +{ + D3DVECTOR pos; + float angle, a, g, cirSpeed, progress; + int i; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + if ( m_bBee ) // bee? + { + return TRUE; + } + + if ( m_bTurn ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Direction(a, g)*1.0f; + if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground? + { + cirSpeed *= 4.0f; // more fishing + } + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return TRUE; + } + + if ( m_move != 0 ) // preliminary advance? + { + m_timeLimit -= event.rTime; + m_physics->SetMotorSpeedX(m_move); // forward/backward + return TRUE; + } + + m_progress += event.rTime*m_speed; // others advance + progress = m_progress; + if ( progress > 1.0f ) progress = 1.0f; + + if ( m_bSubm ) // submarine? + { + if ( m_order == TMO_GRAB ) + { + if ( m_step == 0 ) // fall? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-progress*2.0f; + m_object->SetPosition(1, pos); + } + if ( m_step == 1 ) // farm? + { + pos = m_object->RetPosition(2); + pos.z = -1.5f+progress*0.5f; + m_object->SetPosition(2, pos); + + pos = m_object->RetPosition(3); + pos.z = 1.5f-progress*0.5f; + m_object->SetPosition(3, pos); + } + if ( m_step == 2 ) // up? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-(1.0f-progress)*2.0f; + m_object->SetPosition(1, pos); + } + } + else + { + if ( m_step == 0 ) // fall? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-progress*2.0f; + m_object->SetPosition(1, pos); + } + if ( m_step == 1 ) // farm? + { + pos = m_object->RetPosition(2); + pos.z = -1.5f+(1.0f-progress)*0.5f; + m_object->SetPosition(2, pos); + + pos = m_object->RetPosition(3); + pos.z = 1.5f-(1.0f-progress)*0.5f; + m_object->SetPosition(3, pos); + } + if ( m_step == 2 ) // up? + { + pos = m_object->RetPosition(1); + pos.y = 3.0f-(1.0f-progress)*2.0f; + m_object->SetPosition(1, pos); + } + } + } + else + { + for ( i=0 ; i<5 ; i++ ) + { + angle = (m_finalAngle[i]-m_initialAngle[i])*progress; + angle += m_initialAngle[i]; + m_object->SetAngleZ(i+1, angle); + } + } + + return TRUE; +} + + +// Initializes the initial and final angles. + +void CTaskManip::InitAngle() +{ + CObject* power; + float max, energy; + int i; + + if ( m_bSubm || m_bBee ) return; + + if ( m_arm == TMA_NEUTRAL || + m_arm == TMA_GRAB ) + { + m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm + m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm + m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand + } + if ( m_arm == TMA_STOCK ) + { + m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm + m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm + m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand + } + if ( m_arm == TMA_FFRONT ) + { + m_finalAngle[0] = 35.0f*PI/180.0f; // arm + m_finalAngle[1] = -95.0f*PI/180.0f; // forearm + m_finalAngle[2] = -27.0f*PI/180.0f; // hand + } + if ( m_arm == TMA_FBACK ) + { + m_finalAngle[0] = 145.0f*PI/180.0f; // arm + m_finalAngle[1] = 95.0f*PI/180.0f; // forearm + m_finalAngle[2] = 27.0f*PI/180.0f; // hand + } + if ( m_arm == TMA_POWER ) + { + m_finalAngle[0] = 95.0f*PI/180.0f; // arm + m_finalAngle[1] = 125.0f*PI/180.0f; // forearm + m_finalAngle[2] = 50.0f*PI/180.0f; // hand + } + if ( m_arm == TMA_OTHER ) + { + if ( m_height <= 3.0f ) + { + m_finalAngle[0] = 55.0f*PI/180.0f; // arm + m_finalAngle[1] = -90.0f*PI/180.0f; // forearm + m_finalAngle[2] = -35.0f*PI/180.0f; // hand + } + else + { + m_finalAngle[0] = 70.0f*PI/180.0f; // arm + m_finalAngle[1] = -90.0f*PI/180.0f; // forearm + m_finalAngle[2] = -50.0f*PI/180.0f; // hand + } + } + + if ( m_hand == TMH_OPEN ) // open clamp? + { + m_finalAngle[3] = -PI*0.10f; // clamp close + m_finalAngle[4] = PI*0.10f; // clamp remote + } + if ( m_hand == TMH_CLOSE ) // clamp closed? + { + m_finalAngle[3] = PI*0.05f; // clamp close + m_finalAngle[4] = -PI*0.05f; // clamp remote + } + + for ( i=0 ; i<5 ; i++ ) + { + m_initialAngle[i] = m_object->RetAngleZ(i+1); + } + + max = 0.0f; + for ( i=0 ; i<5 ; i++ ) + { + max = Max(max, Abs(m_initialAngle[i] - m_finalAngle[i])); + } + m_speed = (PI*1.0f)/max; + if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?) + + energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + } + + if ( energy == 0.0f ) + { + m_speed *= 0.7f; // slower if more energy! + } +} + + +// Tests whether an object is compatible with the operation TMA_OTHER. + +BOOL TestFriend(ObjectType oType, ObjectType fType) +{ + if ( oType == OBJECT_ENERGY ) + { + return ( fType == OBJECT_METAL ); + } + if ( oType == OBJECT_LABO ) + { + return ( fType == OBJECT_BULLET ); + } + if ( oType == OBJECT_NUCLEAR ) + { + return ( fType == OBJECT_URANIUM ); + } + + return ( fType == OBJECT_POWER || + fType == OBJECT_ATOMIC ); +} + +// Assigns the goal was achieved. + +Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) +{ + ObjectType type; + CObject *front, *other, *power; + CPyro *pyro; + float iAngle, dist, len; + float fDist, fAngle, oDist, oAngle, oHeight; + D3DVECTOR pos, fPos, oPos; + + m_arm = arm; + m_height = 0.0f; + m_step = 0; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + oAngle = iAngle; + + m_bError = TRUE; // operation impossible + + if ( m_arm != TMA_FFRONT && + m_arm != TMA_FBACK && + m_arm != TMA_POWER && + m_arm != TMA_GRAB ) return ERR_MANIP_VEH; + + m_physics->SetMotorSpeed(D3DVECTOR(0.0f, 0.0f, 0.0f)); + + type = m_object->RetType(); + if ( type == OBJECT_BEE ) // bee? + { + if ( m_object->RetFret() == 0 ) + { + if ( !m_physics->RetLand() ) return ERR_MANIP_FLY; + + other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE); + if ( other == 0 ) return ERR_MANIP_NIL; + m_object->SetFret(other); // takes the ball + other->SetTruck(m_object); + other->SetTruckPart(0); // taken with the base + other->SetPosition(0, D3DVECTOR(0.0f, -3.0f, 0.0f)); + } + else + { + other = m_object->RetFret(); // other = ball + m_object->SetFret(0); // lick the ball + other->SetTruck(0); + pos = m_object->RetPosition(0); + pos.y -= 3.0f; + other->SetPosition(0, pos); + + pos = m_object->RetPosition(0); + pos.y += 2.0f; + m_object->SetPosition(0, pos); // against the top of jump + + pyro = new CPyro(m_iMan); + pyro->Create(PT_FALL, other); // the ball falls + } + + m_bBee = TRUE; + m_bError = FALSE; // ok + return ERR_OK; + } + m_bBee = FALSE; + + m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine? + + if ( m_arm == TMA_GRAB ) // takes immediately? + { + TruckTakeObject(); + Abort(); + return ERR_OK; + } + + m_energy = 0.0f; + power = m_object->RetPower(); + if ( power != 0 ) + { + m_energy = power->RetEnergy(); + } + + if ( !m_physics->RetLand() ) return ERR_MANIP_FLY; + + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH; + + if ( m_bSubm ) // submarine? + { + m_arm = TMA_FFRONT; // only possible in front! + } + + m_move = 0.0f; // advance not necessary + m_angle = iAngle; + + if ( order == TMO_AUTO ) + { + if ( m_object->RetFret() == 0 ) + { + m_order = TMO_GRAB; + } + else + { + m_order = TMO_DROP; + } + } + else + { + m_order = order; + } + + if ( m_order == TMO_GRAB && m_object->RetFret() != 0 ) + { + return ERR_MANIP_BUSY; + } + if ( m_order == TMO_DROP && m_object->RetFret() == 0 ) + { + return ERR_MANIP_EMPTY; + } + +//? speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + if ( m_order == TMO_GRAB ) + { + if ( m_arm == TMA_FFRONT ) + { + front = SearchTakeFrontObject(TRUE, fPos, fDist, fAngle); + other = SearchOtherObject(TRUE, oPos, oDist, oAngle, oHeight); + + if ( front != 0 && fDist < oDist ) + { + m_targetPos = fPos; + m_angle = fAngle; + m_move = 1.0f; // advance required + } + else if ( other != 0 && oDist < fDist ) + { + if ( other->RetPower() == 0 ) return ERR_MANIP_NIL; + m_targetPos = oPos; + m_angle = oAngle; + m_height = oHeight; + m_move = 1.0f; // advance required + m_arm = TMA_OTHER; + } + else + { + return ERR_MANIP_NIL; + } + m_main->HideDropZone(front); // hides buildable area + } + if ( m_arm == TMA_FBACK ) + { + if ( SearchTakeBackObject(TRUE, m_targetPos, fDist, m_angle) == 0 ) + { + return ERR_MANIP_NIL; + } + m_angle += PI; + m_move = -1.0f; // back necessary + } + if ( m_arm == TMA_POWER ) + { + if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL; + } + } + + if ( m_order == TMO_DROP ) + { + if ( m_arm == TMA_FFRONT ) + { + other = SearchOtherObject(TRUE, oPos, oDist, oAngle, oHeight); + if ( other != 0 && other->RetPower() == 0 ) + { + m_targetPos = oPos; + m_angle = oAngle; + m_height = oHeight; + m_move = 1.0f; // advance required + m_arm = TMA_OTHER; + } + else + { + if ( !IsFreeDeposeObject(D3DVECTOR(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; + } + } + if ( m_arm == TMA_FBACK ) + { + if ( !IsFreeDeposeObject(D3DVECTOR(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; + } + if ( m_arm == TMA_POWER ) + { + if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC; + } + } + + dist = Length(m_object->RetPosition(0), m_targetPos); + len = dist-TAKE_DIST; + if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER; + if ( len < 0.0f ) len = 0.0f; + if ( m_arm == TMA_FBACK ) len = -len; + m_advanceLength = dist-m_physics->RetLinLength(len); + if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance + + if ( m_energy == 0.0f ) m_move = 0.0f; + + if ( m_move != 0.0f ) // forward or backward? + { + m_timeLimit = m_physics->RetLinTimeLength(Abs(len))*1.5f; + if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f; + } + + if ( m_object->RetFret() == 0 ) // not carrying anything? + { + m_hand = TMH_OPEN; // open clamp + } + else + { + m_hand = TMH_CLOSE; // closed clamp + } + + InitAngle(); + + if ( iAngle == m_angle || m_energy == 0.0f ) + { + m_bTurn = FALSE; // preliminary rotation unnecessary + SoundManip(1.0f/m_speed); + } + else + { + m_bTurn = TRUE; // preliminary rotation necessary + } + + if ( m_bSubm ) + { + m_camera->StartCentering(m_object, PI*0.8f, 99.9f, 0.0f, 0.5f); + } + + m_physics->SetFreeze(TRUE); // it does not move + + m_bError = FALSE; // ok + return ERR_OK; +} + +// Indicates whether the action is complete. + +Error CTaskManip::IsEnded() +{ + CObject* fret; + D3DVECTOR pos; + float angle, dist; + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_bBee ) // bee? + { + return ERR_STOP; + } + + if ( m_bTurn ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = NormAngle(angle); // 0..2*PI + + if ( TestAngle(angle, m_angle-PI*0.01f, m_angle+PI*0.01f) ) + { + m_bTurn = FALSE; // rotation ended + m_physics->SetMotorSpeedZ(0.0f); + if ( m_move == 0.0f ) + { + SoundManip(1.0f/m_speed); + } + } + return ERR_CONTINUE; + } + + if ( m_move != 0.0f ) // preliminary advance? + { + if ( m_timeLimit <= 0.0f ) + { +//OK 1.9 + dist = Length(m_object->RetPosition(0), m_targetPos); + if ( dist <= m_advanceLength + 2.0f ) + { + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); + SoundManip(1.0f/m_speed); + return ERR_CONTINUE; + } + else + { +//EOK 1.9 + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); // stops + Abort(); + return ERR_STOP; + } + } + + dist = Length(m_object->RetPosition(0), m_targetPos); + if ( dist <= m_advanceLength ) + { + m_move = 0.0f; // advance ended + m_physics->SetMotorSpeedX(0.0f); + SoundManip(1.0f/m_speed); + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( !m_bSubm ) + { + for ( i=0 ; i<5 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + m_step ++; + + if ( m_order == TMO_GRAB ) + { + if ( m_step == 1 ) + { + if ( m_bSubm ) m_speed = 1.0f/0.7f; + m_hand = TMH_CLOSE; // closes the clamp to take + InitAngle(); + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + return ERR_CONTINUE; + } + if ( m_step == 2 ) + { + if ( m_bSubm ) m_speed = 1.0f/1.5f; + if ( !TruckTakeObject() && + m_object->RetFret() == 0 ) + { + m_hand = TMH_OPEN; // reopens the clamp + m_arm = TMA_NEUTRAL; + InitAngle(); + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + } + else + { + if ( (m_arm == TMA_OTHER || + m_arm == TMA_POWER ) && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0)); + } + m_arm = TMA_STOCK; + InitAngle(); + SoundManip(1.0f/m_speed); + } + return ERR_CONTINUE; + } + } + + if ( m_order == TMO_DROP ) + { + if ( m_step == 1 ) + { + if ( m_bSubm ) m_speed = 1.0f/0.7f; + fret = m_object->RetFret(); + if ( TruckDeposeObject() ) + { + if ( (m_arm == TMA_OTHER || + m_arm == TMA_POWER ) && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWERON, m_object->RetPosition(0)); + } + if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT ) + { + m_main->ShowDropZone(fret, m_object); // shows buildable area + } + m_hand = TMH_OPEN; // opens the clamp to deposit + SoundManip(1.0f/m_speed, 0.8f, 1.5f); + } + InitAngle(); + return ERR_CONTINUE; + } + if ( m_step == 2 ) + { + if ( m_bSubm ) m_speed = 1.0f/1.5f; + m_arm = TMA_NEUTRAL; + InitAngle(); + SoundManip(1.0f/m_speed); + return ERR_CONTINUE; + } + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskManip::Abort() +{ + int i; + + if ( m_object->RetFret() == 0 ) // not carrying anything? + { + m_hand = TMH_OPEN; // open clamp + m_arm = TMA_NEUTRAL; + } + else + { + m_hand = TMH_CLOSE; // closed clamp + m_arm = TMA_STOCK; + } + InitAngle(); + + if ( !m_bSubm ) + { + for ( i=0 ; i<5 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(FALSE); // is moving again + return TRUE; +} + + +// Seeks the object below to take (for bees). + +CObject* CTaskManip::SearchTakeUnderObject(D3DVECTOR &pos, float dLimit) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float min, distance; + int i; + + iPos = m_object->RetPosition(0); + + min = 1000000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Length(oPos, iPos); + if ( distance <= dLimit && + distance < min ) + { + min = distance; + pBest = pObj; + } + } + if ( pBest != 0 ) + { + pos = pBest->RetPosition(0); + } + return pBest; +} + +// Seeks the object in front to take. + +CObject* CTaskManip::SearchTakeFrontObject(BOOL bAdvance, D3DVECTOR &pos, + float &distance, float &angle) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, aLimit, dLimit, f; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*PI/180.0f; + dLimit = MARGIN_FRONT+10.0f; + } + else + { +//? aLimit = 7.0f*PI/180.0f; + aLimit = 15.0f*PI/180.0f; //OK 1.9 + dLimit = MARGIN_FRONT; + } + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT && + type != OBJECT_SCRAP1 && + type != OBJECT_SCRAP2 && + type != OBJECT_SCRAP3 && + type != OBJECT_SCRAP4 && + type != OBJECT_SCRAP5 ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Abs(Length(oPos, iPos)-TAKE_DIST); + f = 1.0f-distance/50.0f; + if ( f < 0.5f ) f = 0.5f; + + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( !TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue; + + if ( distance < -dLimit || + distance > dLimit ) continue; + + if ( distance < min ) + { + min = distance; + pBest = pObj; + bAngle = angle; + } + } + if ( pBest == 0 ) + { + distance = 1000000.0f; + angle = 0.0f; + } + else + { + pos = pBest->RetPosition(0); + distance = min; + angle = bAngle; + } + return pBest; +} + +// Seeks the object back to take. + +CObject* CTaskManip::SearchTakeBackObject(BOOL bAdvance, D3DVECTOR &pos, + float &distance, float &angle) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, aLimit, dLimit, f; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0)+PI; + iAngle = NormAngle(iAngle); // 0..2*PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*PI/180.0f; + dLimit = MARGIN_BACK+5.0f; + } + else + { + aLimit = 7.0f*PI/180.0f; + dLimit = MARGIN_BACK; + } + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT && + type != OBJECT_SCRAP1 && + type != OBJECT_SCRAP2 && + type != OBJECT_SCRAP3 && + type != OBJECT_SCRAP4 && + type != OBJECT_SCRAP5 ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Abs(Length(oPos, iPos)-TAKE_DIST); + f = 1.0f-distance/50.0f; + if ( f < 0.5f ) f = 0.5f; + + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( !TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue; + + if ( distance < -dLimit || + distance > dLimit ) continue; + + if ( distance < min ) + { + min = distance; + pBest = pObj; + bAngle = angle; + } + } + if ( pBest == 0 ) + { + distance = 1000000.0f; + angle = 0.0f; + } + else + { + pos = pBest->RetPosition(0); + distance = min; + angle = bAngle; + } + return pBest; +} + +// Seeks the robot or building on which it wants to put a battery or or other object. + +CObject* CTaskManip::SearchOtherObject(BOOL bAdvance, D3DVECTOR &pos, + float &distance, float &angle, + float &height) +{ + Character* character; + CObject* pObj; + CObject* pPower; + D3DMATRIX* mat; + D3DVECTOR iPos, oPos; + ObjectType type, powerType; + float iAngle, iRad, oAngle, oLimit, aLimit, dLimit; + int i; + + distance = 1000000.0f; + angle = 0.0f; + + if ( m_bSubm ) return 0; // impossible with the submarine + + if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0; + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + if ( bAdvance && m_energy > 0.0f ) + { + aLimit = 60.0f*PI/180.0f; + dLimit = MARGIN_FRIEND+10.0f; + } + else + { + aLimit = 7.0f*PI/180.0f; + dLimit = MARGIN_FRIEND; + } + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; // yourself? + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_TOWER && + type != OBJECT_RESEARCH && + type != OBJECT_ENERGY && + type != OBJECT_LABO && + type != OBJECT_NUCLEAR ) continue; + + pPower = pObj->RetPower(); + if ( pPower != 0 ) + { + if ( pPower->RetLock() ) continue; + if ( pPower->RetZoomY(0) != 1.0f ) continue; + + powerType = pPower->RetType(); + if ( powerType == OBJECT_NULL || + powerType == OBJECT_FIX ) continue; + } + + mat = pObj->RetWorldMatrix(0); + character = pObj->RetCharacter(); + oPos = Transform(*mat, character->posPower); + + oAngle = pObj->RetAngleY(0); + if ( type == OBJECT_TOWER || + type == OBJECT_RESEARCH ) + { + oLimit = 45.0f*PI/180.0f; + } + else if ( type == OBJECT_ENERGY ) + { + oLimit = 90.0f*PI/180.0f; + } + else if ( type == OBJECT_LABO ) + { + oLimit = 120.0f*PI/180.0f; + } + else if ( type == OBJECT_NUCLEAR ) + { + oLimit = 45.0f*PI/180.0f; + } + else + { + oLimit = 45.0f*PI/180.0f; + oAngle += PI; // is behind + } + oAngle = NormAngle(oAngle); // 0..2*PI + angle = RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW ! + if ( !TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue; + + distance = Abs(Length(oPos, iPos)-TAKE_DIST); + if ( distance <= dLimit ) + { + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + character = pObj->RetCharacter(); + height = character->posPower.y; + pos = oPos; + return pObj; + } + } + } + + distance = 1000000.0f; + angle = 0.0f; + return 0; +} + +// Takes the object placed in front. + +BOOL CTaskManip::TruckTakeObject() +{ + CObject* fret; + CObject* other; + D3DMATRIX matRotate; + D3DVECTOR pos; + float angle, dist; + + if ( m_arm == TMA_GRAB ) // takes immediately? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; // nothing to take? + m_fretType = fret->RetType(); + + if ( m_object->RetType() == OBJECT_HUMAN || + m_object->RetType() == OBJECT_TECH ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + + fret->SetPosition(0, D3DVECTOR(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + } + else if ( m_bSubm ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(2); // takes with the right claw + + pos = D3DVECTOR(1.1f, -1.0f, 1.0f); // relative + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleY(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + } + else + { + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = D3DVECTOR(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, PI/2.0f); + fret->SetAngleY(0, 0.0f); + } + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_FFRONT ) // takes on the ground in front? + { + fret = SearchTakeFrontObject(FALSE, pos, dist, angle); + if ( fret == 0 ) return FALSE; // nothing to take? + m_fretType = fret->RetType(); + + if ( m_bSubm ) + { + fret->SetTruck(m_object); + fret->SetTruckPart(2); // takes with the right claw + + pos = D3DVECTOR(1.1f, -1.0f, 1.0f); // relative + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleY(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + } + else + { + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = D3DVECTOR(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, PI/2.0f); + fret->SetAngleY(0, 0.0f); + } + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_FBACK ) // takes on the ground behind? + { + fret = SearchTakeBackObject(FALSE, pos, dist, angle); + if ( fret == 0 ) return FALSE; // nothing to take? + m_fretType = fret->RetType(); + + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = D3DVECTOR(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, PI/2.0f); + fret->SetAngleY(0, 0.0f); + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_POWER ) // takes battery in the back? + { + fret = m_object->RetPower(); + if ( fret == 0 ) return FALSE; // no battery? + m_fretType = fret->RetType(); + + pos = D3DVECTOR(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, PI/2.0f); + fret->SetAngleY(0, 0.0f); + fret->SetTruckPart(3); // takes with the hand + + m_object->SetPower(0); + m_object->SetFret(fret); // takes + } + + if ( m_arm == TMA_OTHER ) // battery takes from friend? + { + other = SearchOtherObject(FALSE, pos, dist, angle, m_height); + if ( other == 0 ) return FALSE; + + fret = other->RetPower(); + if ( fret == 0 ) return FALSE; // the other does not have a battery? + m_fretType = fret->RetType(); + + other->SetPower(0); + fret->SetTruck(m_object); + fret->SetTruckPart(3); // takes with the hand + + pos = D3DVECTOR(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) + fret->SetPosition(0, pos); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, PI/2.0f); + fret->SetAngleY(0, 0.0f); + + m_object->SetFret(fret); // takes + } + + return TRUE; +} + +// Deposes the object taken. + +BOOL CTaskManip::TruckDeposeObject() +{ + Character* character; + CObject* fret; + CObject* other; + D3DMATRIX* mat; + D3DVECTOR pos; + float angle, dist; + + if ( m_arm == TMA_FFRONT ) // deposits on the ground in front? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; // nothing transported? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(0.0f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->FloorAdjust(); // plate well on the ground + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TMA_FBACK ) // deposited on the ground behind? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; // nothing transported? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(0.0f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TMA_POWER ) // deposits battery in the back? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; // nothing transported? + m_fretType = fret->RetType(); + + if ( m_object->RetPower() != 0 ) return FALSE; + + fret->SetTruck(m_object); + fret->SetTruckPart(0); // carried by the base + + character = m_object->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + + m_object->SetPower(fret); // uses + m_object->SetFret(0); + } + + if ( m_arm == TMA_OTHER ) // deposits battery on friend? + { + other = SearchOtherObject(FALSE, pos, dist, angle, m_height); + if ( other == 0 ) return FALSE; + + fret = other->RetPower(); + if ( fret != 0 ) return FALSE; // the other already has a battery? + + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; + m_fretType = fret->RetType(); + + other->SetPower(fret); + fret->SetTruck(other); + + character = other->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->SetTruckPart(0); // carried by the base + + m_object->SetFret(0); // deposit + } + + return TRUE; +} + +// Seeks if a location allows to deposit an object. + +BOOL CTaskManip::IsFreeDeposeObject(D3DVECTOR pos) +{ + CObject* pObj; + D3DMATRIX* mat; + D3DVECTOR iPos, oPos; + float oRadius; + int i, j; + + mat = m_object->RetWorldMatrix(0); + iPos = Transform(*mat, pos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( Length(iPos, oPos)-(oRadius+1.0f) < 2.0f ) + { + return FALSE; // location occupied + } + } + } + return TRUE; // location free +} + +// Plays the sound of the manipulator arm. + +void CTaskManip::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, TRUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + diff --git a/src/object/task/taskmanip.h b/src/object/task/taskmanip.h new file mode 100644 index 0000000..bc746cf --- /dev/null +++ b/src/object/task/taskmanip.h @@ -0,0 +1,109 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskmanip.h + +#ifndef _TASKMANIP_H_ +#define _TASKMANIP_H_ + + +#include "task.h" +#include "misc.h" +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskManipOrder +{ + TMO_AUTO = 0, // deposits or takes automatically + TMO_GRAB = 1, // takes an object + TMO_DROP = 2, // deposits the object +}; + +enum TaskManipArm +{ + TMA_NEUTRAL = 1, // empty arm at rest + TMA_STOCK = 2, // right arm resting + TMA_FFRONT = 3, // arm on the ground + TMA_FBACK = 4, // arm behind the robot + TMA_POWER = 5, // arm behind the robot + TMA_OTHER = 6, // arm behind a friend robot + TMA_GRAB = 7, // takes immediately +}; + +enum TaskManipHand +{ + TMH_OPEN = 1, // open clamp + TMH_CLOSE = 2, // closed clamp +}; + + + +class CTaskManip : public CTask +{ +public: + CTaskManip(CInstanceManager* iMan, CObject* object); + ~CTaskManip(); + + BOOL EventProcess(const Event &event); + + Error Start(TaskManipOrder order, TaskManipArm arm); + Error IsEnded(); + BOOL Abort(); + +protected: + void InitAngle(); + CObject* SearchTakeUnderObject(D3DVECTOR &pos, float dLimit); + CObject* SearchTakeFrontObject(BOOL bAdvance, D3DVECTOR &pos, float &distance, float &angle); + CObject* SearchTakeBackObject(BOOL bAdvance, D3DVECTOR &pos, float &distance, float &angle); + CObject* SearchOtherObject(BOOL bAdvance, D3DVECTOR &pos, float &distance, float &angle, float &height); + BOOL TruckTakeObject(); + BOOL TruckDeposeObject(); + BOOL IsFreeDeposeObject(D3DVECTOR pos); + void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f); + +protected: + TaskManipOrder m_order; + TaskManipArm m_arm; + TaskManipHand m_hand; + int m_step; + float m_speed; + float m_progress; + float m_initialAngle[5]; + float m_finalAngle[5]; + float m_height; + float m_advanceLength; + float m_energy; + BOOL m_bError; + BOOL m_bTurn; + BOOL m_bSubm; + BOOL m_bBee; + float m_angle; + float m_move; + D3DVECTOR m_targetPos; + float m_timeLimit; + ObjectType m_fretType; +}; + + +#endif //_TASKMANIP_H_ diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp new file mode 100644 index 0000000..7d95f21 --- /dev/null +++ b/src/object/task/taskpen.cpp @@ -0,0 +1,304 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskpen.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "motion.h" +#include "motionant.h" +#include "motionspider.h" +#include "task.h" +#include "taskpen.h" + + + +// Object's constructor. + +CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskPen::~CTaskPen() +{ +} + + +// Management of an event. + +BOOL CTaskPen::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed; + FPOINT dim; + int i; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + if ( m_delay == 0.0f ) + { + m_progress = 1.0f; + } + else + { + m_progress += event.rTime*(1.0f/m_delay); // others advance + if ( m_progress > 1.0f ) m_progress = 1.0f; + } + + m_time += event.rTime; + + if ( m_phase == TPP_UP ) // back the pencil + { + i = AngleToRank(m_object->RetAngleY(1)); + pos = m_object->RetPosition(10+i); + pos.y = -3.2f*(1.0f-m_progress); + m_object->SetPosition(10+i, pos); + } + + if ( m_phase == TPP_TURN ) // turns the carousel? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_supportPos; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = (Rand()-0.5f)*3.0f; + speed.z = (Rand()-0.5f)*3.0f; + speed.y = Rand()*2.0f; + dim.x = Rand()*1.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + + m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress); + } + + if ( m_phase == TPP_DOWN ) // down the pencil? + { + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_supportPos; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = (Rand()-0.5f)*3.0f; + speed.z = (Rand()-0.5f)*3.0f; + speed.y = Rand()*5.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f); + } + + i = AngleToRank(m_object->RetAngleY(1)); + pos = m_object->RetPosition(10+i); + if ( m_timeDown == 0.0f ) + { + pos.y = 0.0f; + } + else + { + pos.y = -3.2f*Bounce(Min(m_progress*1.8f, 1.0f)); + } + m_object->SetPosition(10+i, pos); + } + + return TRUE; +} + + +// Assigns the goal has achieved. + +Error CTaskPen::Start(BOOL bDown, int color) +{ + D3DVECTOR pos; + D3DMATRIX* mat; + ObjectType type; + int i; + + m_bError = TRUE; // operation impossible + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH; + + m_bError = FALSE; // ok + + m_oldAngle = m_object->RetAngleY(1); + m_newAngle = ColorToAngle(color); + + i = AngleToRank(m_oldAngle); + pos = m_object->RetPosition(10+i); + + if ( pos.y == 0.0f ) // pencil at the top? + { + m_timeUp = 0.0f; + } + else // pencil on the bottom? + { + m_timeUp = 1.0f; // must rise up + } + + if ( bDown ) // must go down ? + { + m_timeDown = 0.7f; + } + else + { + m_timeDown = 0.0f; + } + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(-3.0f, 7.0f, 0.0f); + pos = Transform(*mat, pos); // position of carousel + m_supportPos = pos; + + m_phase = TPP_UP; + m_progress = 0.0f; + m_delay = m_timeUp; + m_time = 0.0f; + + if ( m_timeUp > 0.0f ) + { + SoundManip(m_timeUp, 1.0f, 0.5f); + } + + m_lastParticule = 0.0f; + +//? m_camera->StartCentering(m_object, PI*0.60f, 99.9f, 5.0f, 0.5f); + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskPen::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TPP_UP ) + { + m_phase = TPP_TURN; + m_progress = 0.0f; + m_delay = Abs(m_oldAngle-m_newAngle)/PI; + m_time = 0.0f; + m_lastParticule = 0.0f; + if ( m_delay > 0.0f ) + { + SoundManip(m_delay, 1.0f, 1.0f); + } + return ERR_CONTINUE; + } + + if ( m_phase == TPP_TURN ) + { + m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f); + m_phase = TPP_DOWN; + m_progress = 0.0f; + m_delay = m_timeDown; + m_time = 0.0f; + m_lastParticule = 0.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskPen::Abort() +{ +//? m_camera->StopCentering(m_object, 0.5f); + return TRUE; +} + + +// Plays the sound of the manipulator arm. + +void CTaskPen::SoundManip(float time, float amplitude, float frequency) +{ + int i; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, TRUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP); +} + + +// Converting a angle to number of pencil. + +int CTaskPen::AngleToRank(float angle) +{ +//? return (int)(angle/(-45.0f*PI/180.0f)); + angle = -angle; + angle += (45.0f*PI/180.0f)/2.0f; + return (int)(angle/(45.0f*PI/180.0f)); +} + +// Converting a color to the angle of carousel of pencils. + +float CTaskPen::ColorToAngle(int color) +{ + return -45.0f*PI/180.0f*ColorToRank(color); +} + +// Converting a color number to the pencil (0 .. 7). + +int CTaskPen::ColorToRank(int color) +{ + if ( color == 8 ) return 1; // yellow + if ( color == 7 ) return 2; // orange + if ( color == 5 ) return 2; // pink + if ( color == 4 ) return 3; // red + if ( color == 6 ) return 4; // purple + if ( color == 14 ) return 5; // blue + if ( color == 15 ) return 5; // light blue + if ( color == 12 ) return 6; // green + if ( color == 13 ) return 6; // light green + if ( color == 10 ) return 7; // brown + if ( color == 9 ) return 7; // beige + return 0; // black +} + diff --git a/src/object/task/taskpen.h b/src/object/task/taskpen.h new file mode 100644 index 0000000..752a52d --- /dev/null +++ b/src/object/task/taskpen.h @@ -0,0 +1,77 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskpen.h + +#ifndef _TASKSPEN_H_ +#define _TASKSPEN_H_ + + +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskPenPhase +{ + TPP_UP = 1, // rises the pencil + TPP_TURN = 2, // turns the carousel + TPP_DOWN = 3, // descends the pencil +}; + + + +class CTaskPen : public CTask +{ +public: + CTaskPen(CInstanceManager* iMan, CObject* object); + ~CTaskPen(); + + BOOL EventProcess(const Event &event); + + Error Start(BOOL bDown, int color); + Error IsEnded(); + BOOL Abort(); + +protected: + void SoundManip(float time, float amplitude, float frequency); + int AngleToRank(float angle); + float ColorToAngle(int color); + int ColorToRank(int color); + +protected: + BOOL m_bError; + TaskPenPhase m_phase; + float m_progress; + float m_delay; + float m_time; + float m_lastParticule; + D3DVECTOR m_supportPos; + + float m_timeUp; + float m_oldAngle; + float m_newAngle; + float m_timeDown; +}; + + +#endif //_TASKSPEN_H_ diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp new file mode 100644 index 0000000..1284bb5 --- /dev/null +++ b/src/object/task/taskrecover.cpp @@ -0,0 +1,431 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskrecover.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "displaytext.h" +#include "task.h" +#include "taskrecover.h" + + +#define ENERGY_RECOVER 0.25f // energy consumed by recovery +#define RECOVER_DIST 11.8f + + + +// Object's constructor. + +CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_ruin = 0; + m_soundChannel = -1; +} + +// Object's constructor. + +CTaskRecover::~CTaskRecover() +{ +} + + +// Management of an event. + +BOOL CTaskRecover::EventProcess(const Event &event) +{ + CObject* power; + D3DVECTOR pos, speed; + FPOINT dim; + float a, g, cirSpeed, angle, energy, dist, linSpeed; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + if ( m_phase == TRP_TURN ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Direction(a, g)*1.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return TRUE; + } + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TRP_DOWN ) + { + angle = Prop(126, -10, m_progress); + m_object->SetAngleZ(2, angle); + m_object->SetAngleZ(4, angle); + + angle = Prop(-144, 0, m_progress); + m_object->SetAngleZ(3, angle); + m_object->SetAngleZ(5, angle); + } + + if ( m_phase == TRP_MOVE ) // preliminary forward/backward? + { + dist = Length(m_object->RetPosition(0), m_ruin->RetPosition(0)); + linSpeed = 0.0f; + if ( dist > RECOVER_DIST ) linSpeed = 1.0f; + if ( dist < RECOVER_DIST ) linSpeed = -1.0f; + m_physics->SetMotorSpeedX(linSpeed); // forward/backward + return TRUE; + } + + if ( m_phase == TRP_OPER ) + { + power = m_object->RetPower(); + if ( power != 0 ) + { + energy = power->RetEnergy(); + power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed); + } + + speed.x = (Rand()-0.5f)*0.1f*m_progress; + speed.y = (Rand()-0.5f)*0.1f*m_progress; + speed.z = (Rand()-0.5f)*0.1f*m_progress; + m_ruin->SetCirVibration(speed); + + if ( m_progress >= 0.75f ) + { + m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f); + } + + if ( m_progress > 0.5f && m_progress < 0.8f ) + { + m_metal->SetZoom(0, (m_progress-0.5f)/0.3f); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_recoverPos; + pos.x += (Rand()-0.5f)*8.0f*(1.0f-m_progress); + pos.z += (Rand()-0.5f)*8.0f*(1.0f-m_progress); + pos.y -= 4.0f; + speed.x = (Rand()-0.5f)*0.0f; + speed.z = (Rand()-0.5f)*0.0f; + speed.y = Rand()*15.0f; + dim.x = Rand()*2.0f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f); + } + } + + if ( m_phase == TRP_UP ) + { + angle = Prop(-10, 126, m_progress); + m_object->SetAngleZ(2, angle); + m_object->SetAngleZ(4, angle); + + angle = Prop(0, -144, m_progress); + m_object->SetAngleZ(3, angle); + m_object->SetAngleZ(5, angle); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_recoverPos; + pos.y -= 4.0f; + speed.x = (Rand()-0.5f)*0.0f; + speed.z = (Rand()-0.5f)*0.0f; + speed.y = Rand()*15.0f; + dim.x = Rand()*2.0f+1.5f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f); + } + } + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskRecover::Start() +{ + CObject* power; + D3DMATRIX* mat; + D3DVECTOR pos, iPos, oPos; + float energy; + + ObjectType type; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_RECOVER_ENERGY; + energy = power->RetEnergy(); + if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(RECOVER_DIST, 3.3f, 0.0f); + pos = Transform(*mat, pos); // position in front + m_recoverPos = pos; + + m_ruin = SearchRuin(); + if ( m_ruin == 0 ) return ERR_RECOVER_NULL; + m_ruin->SetLock(TRUE); // ruin no longer usable + + iPos = m_object->RetPosition(0); + oPos = m_ruin->RetPosition(0); + m_angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + + m_metal = 0; + + m_phase = TRP_TURN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + + m_bError = FALSE; // ok + + m_camera->StartCentering(m_object, PI*0.85f, 99.9f, 10.0f, 3.0f); + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskRecover::IsEnded() +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed, goal; + FPOINT dim; + float angle, dist, time; + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TRP_TURN ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = NormAngle(angle); // 0..2*PI + + if ( TestAngle(angle, m_angle-PI*0.01f, m_angle+PI*0.01f) ) + { + m_physics->SetMotorSpeedZ(0.0f); + + dist = Length(m_object->RetPosition(0), m_ruin->RetPosition(0)); + if ( dist > RECOVER_DIST ) + { + time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f); + m_speed = 1.0f/time; + } + else + { + time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f); + m_speed = 1.0f/time; + } + m_phase = TRP_MOVE; + m_progress = 0.0f; + } + return ERR_CONTINUE; + } + + if ( m_phase == TRP_MOVE ) // preliminary advance? + { + dist = Length(m_object->RetPosition(0), m_ruin->RetPosition(0)); + + if ( dist >= RECOVER_DIST-1.0f && + dist <= RECOVER_DIST+1.0f ) + { + m_physics->SetMotorSpeedX(0.0f); + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(RECOVER_DIST, 3.3f, 0.0f); + pos = Transform(*mat, pos); // position in front + m_recoverPos = pos; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, TRUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP); + + m_phase = TRP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/1.5f; + m_time = 0.0f; + } + else + { + if ( m_progress > 1.0f ) // timeout? + { + m_ruin->SetLock(FALSE); // usable again + m_camera->StopCentering(m_object, 2.0f); + return ERR_RECOVER_NULL; + } + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TRP_DOWN ) + { + m_metal = new CObject(m_iMan); + if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) ) + { + delete m_metal; + m_metal = 0; + Abort(); + m_bError = TRUE; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return ERR_STOP; + } + m_metal->SetLock(TRUE); // metal not yet usable + m_metal->SetZoom(0, 0.0f); + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(RECOVER_DIST, 3.1f, 3.9f); + pos = Transform(*mat, pos); + goal = D3DVECTOR(RECOVER_DIST, 3.1f, -3.9f); + goal = Transform(*mat, goal); + m_particule->CreateRay(pos, goal, PARTIRAY2, + FPOINT(2.0f, 2.0f), 8.0f); + + m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP); + + m_phase = TRP_OPER; + m_speed = 1.0f/8.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TRP_OPER ) + { + m_metal->SetZoom(0, 1.0f); + + m_ruin->DeleteObject(); // destroys the ruin + delete m_ruin; + m_ruin = 0; + + m_soundChannel = -1; + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, TRUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP); + + m_phase = TRP_UP; + m_speed = 1.0f/1.5f; + return ERR_CONTINUE; + } + + m_metal->SetLock(FALSE); // metal usable + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskRecover::Abort() +{ + m_object->SetAngleZ(2, 126.0f*PI/180.0f); + m_object->SetAngleZ(4, 126.0f*PI/180.0f); + m_object->SetAngleZ(3, -144.0f*PI/180.0f); + m_object->SetAngleZ(5, -144.0f*PI/180.0f); // rest + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + return TRUE; +} + + +// Seeks if a ruin is in front of the vehicle. + +CObject* CTaskRecover::SearchRuin() +{ + CObject *pObj, *pBest; + D3DVECTOR oPos; + ObjectType type; + float dist, min; + int i; + + pBest = 0; + min = 100000.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_RUINmobilew1 || + type == OBJECT_RUINmobilew2 || + type == OBJECT_RUINmobilet1 || + type == OBJECT_RUINmobilet2 || + type == OBJECT_RUINmobiler1 || + type == OBJECT_RUINmobiler2 ) // vehicle in ruin? + { + oPos = pObj->RetPosition(0); + dist = Length(oPos, m_recoverPos); + if ( dist > 40.0f ) continue; + + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + + } + return pBest; +} + diff --git a/src/object/task/taskrecover.h b/src/object/task/taskrecover.h new file mode 100644 index 0000000..cc2adce --- /dev/null +++ b/src/object/task/taskrecover.h @@ -0,0 +1,75 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskrecover.h + +#ifndef _TASKSRECOVER_H_ +#define _TASKSRECOVER_H_ + + +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskRecoverPhase +{ + TRP_TURN = 1, // turns + TRP_MOVE = 2, // advance + TRP_DOWN = 3, // descends + TRP_OPER = 4, // operates + TRP_UP = 5, // back +}; + + + +class CTaskRecover : public CTask +{ +public: + CTaskRecover(CInstanceManager* iMan, CObject* object); + ~CTaskRecover(); + + BOOL EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + BOOL Abort(); + +protected: + CObject* SearchRuin(); + +protected: + TaskRecoverPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_angle; + float m_lastParticule; + BOOL m_bError; + CObject* m_ruin; + CObject* m_metal; + D3DVECTOR m_recoverPos; + int m_soundChannel; +}; + + +#endif //_TASKSRECOVER_H_ diff --git a/src/object/task/taskreset.cpp b/src/object/task/taskreset.cpp new file mode 100644 index 0000000..a626c02 --- /dev/null +++ b/src/object/task/taskreset.cpp @@ -0,0 +1,345 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskreset.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "sound.h" +#include "robotmain.h" +#include "task.h" +#include "taskreset.h" + + + +#define RESET_DELAY_ZOOM 0.7f +#define RESET_DELAY_MOVE 0.7f + + + + +// Object's constructor. + +CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskReset::~CTaskReset() +{ +} + + +// Management of an event. + +BOOL CTaskReset::EventProcess(const Event &event) +{ + D3DVECTOR pos, speed; + FPOINT dim; + float angle, duration; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_time += event.rTime; + m_progress += event.rTime*m_speed; + + if ( m_phase == TRSP_ZOUT ) + { + angle = m_iAngle; + angle += powf(m_progress*5.0f, 2.0f); // accelerates + m_object->SetAngleY(0, angle); + m_object->SetZoom(0, 1.0f-m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_begin; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Rand()*5.0f; + dim.x = Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + + pos = m_begin; + speed.x = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + speed.y = Rand()*10.0f; + speed *= 1.0f-m_progress*0.5f; + pos += speed*1.5f; + speed = -speed; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Rand()*1.5f+1.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + if ( m_phase == TRSP_MOVE ) + { + pos = m_begin+(m_goal-m_begin)*m_progress; + m_object->SetPosition(0, pos); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 2.0f+Rand()*2.0f; + dim.x = Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + } + } + + if ( m_phase == TRSP_ZIN ) + { + angle = m_angle.y; + angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows + m_object->SetAngleY(0, angle); + m_object->SetZoom(0, m_progress); + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_goal; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = 0.0f; + speed.z = 0.0f; + speed.y = 5.0f+Rand()*5.0f; + dim.x = Rand()*2.0f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f); + + pos = m_goal; + speed.x = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + speed.y = Rand()*10.0f; + speed *= 0.5f+m_progress*0.5f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Rand()*1.5f+1.5f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK6, + duration, 0.0f, + duration*0.9f, 0.7f); + } + } + + return TRUE; +} + + +// Assigns the goal was achieved. +// A positive angle makes a turn right. + +Error CTaskReset::Start(D3DVECTOR goal, D3DVECTOR angle) +{ + CObject* fret; + int i; + + fret = m_object->RetFret(); + if ( fret != 0 && fret->RetResetCap() == RESET_MOVE ) + { + fret->SetTruck(0); + m_object->SetFret(0); // does nothing + } + + if ( !m_main->RetNiceReset() ) // quick return? + { + m_object->SetPosition(0, goal); + m_object->SetAngle(0, angle); + m_brain->RunProgram(m_object->RetResetRun()); + + m_bError = FALSE; + return ERR_OK; + } + + m_begin = m_object->RetPosition(0); + m_goal = goal; + m_angle = angle; + + if ( SearchVehicle() ) // starting location occupied? + { + m_bError = TRUE; + return ERR_RESET_NEAR; + } + + m_iAngle = m_object->RetAngleY(0); + m_time = 0.0f; + m_phase = TRSP_ZOUT; + m_speed = 1.0f/RESET_DELAY_ZOOM; + m_progress = 0.0f; + m_lastParticule = 0.0f; + + m_object->SetResetBusy(TRUE); + + i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, TRUE); + m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP); + + m_bError = FALSE; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskReset::IsEnded() +{ + CObject* power; + float dist; + int i; + + if ( !m_main->RetNiceReset() ) // quick return? + { + return ERR_STOP; + } + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + if ( m_progress < 1.0f ) return ERR_CONTINUE; + + if ( m_phase == TRSP_ZOUT ) + { + dist = Length(m_begin, m_goal); + m_phase = TRSP_MOVE; + m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f); + m_progress = 0.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TRSP_MOVE ) + { + m_object->SetPosition(0, m_goal); + m_object->SetAngle(0, m_angle); + + i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, TRUE); + m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP); + + m_phase = TRSP_ZIN; + m_speed = 1.0f/RESET_DELAY_ZOOM; + m_progress = 0.0f; + return ERR_CONTINUE; + } + + m_object->SetAngle(0, m_angle); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(power->RetCapacity()); // refueling + } + + m_brain->RunProgram(m_object->RetResetRun()); + m_object->SetResetBusy(FALSE); + return ERR_STOP; +} + + +// Seeks if a vehicle is too close. + +BOOL CTaskReset::SearchVehicle() +{ + CObject* pObj; + D3DVECTOR oPos; + ObjectType type; + float oRadius, dist; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + + type = pObj->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_TECH && + type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_MOBILEdr && + type != OBJECT_MOTHER && + type != OBJECT_ANT && + type != OBJECT_SPIDER && + type != OBJECT_BEE && + type != OBJECT_WORM ) continue; + + if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue; + dist = Length(oPos, m_goal)-oRadius; + + if ( dist < 5.0f ) return TRUE; + } + + return FALSE; +} + diff --git a/src/object/task/taskreset.h b/src/object/task/taskreset.h new file mode 100644 index 0000000..a866d1f --- /dev/null +++ b/src/object/task/taskreset.h @@ -0,0 +1,73 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskreset.h + +#ifndef _TASKRESET_H_ +#define _TASKRESET_H_ + + +#include "misc.h" +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskResetPhase +{ + TRSP_ZOUT = 1, // disappears + TRSP_MOVE = 2, // moves + TRSP_ZIN = 3, // reappears +}; + + + +class CTaskReset : public CTask +{ +public: + CTaskReset(CInstanceManager* iMan, CObject* object); + ~CTaskReset(); + + BOOL EventProcess(const Event &event); + + Error Start(D3DVECTOR goal, D3DVECTOR angle); + Error IsEnded(); + +protected: + BOOL SearchVehicle(); + +protected: + D3DVECTOR m_begin; + D3DVECTOR m_goal; + D3DVECTOR m_angle; + + TaskResetPhase m_phase; + BOOL m_bError; + float m_time; + float m_speed; + float m_progress; + float m_lastParticule; // time of generation last particle + float m_iAngle; +}; + + +#endif //_TASKRESET_H_ diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp new file mode 100644 index 0000000..8857e35 --- /dev/null +++ b/src/object/task/tasksearch.cpp @@ -0,0 +1,334 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// tasksearch.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "displaytext.h" +#include "task.h" +#include "tasksearch.h" + + + + +// Object's constructor. + +CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_hand = TSH_UP; +} + +// Object's destructor. + +CTaskSearch::~CTaskSearch() +{ +} + + +// Management of an event. + +BOOL CTaskSearch::EventProcess(const Event &event) +{ + D3DMATRIX* mat; + D3DVECTOR pos, speed; + FPOINT dim; + float angle; + int i; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TSP_DOWN || + m_phase == TSP_UP ) + { + for ( i=0 ; i<3 ; i++ ) + { + angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress; + angle += m_initialAngle[i]; + m_object->SetAngleZ(i+1, angle); + } + } + + if ( m_phase == TSP_SEARCH && + m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(6.5f, 0.2f, 0.0f); + pos = Transform(*mat, pos); // sensor position + + speed.x = (Rand()-0.5f)*20.0f; + speed.z = (Rand()-0.5f)*20.0f; + speed.y = 0.0f; + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIGAS); + } + + return TRUE; +} + + +// Initializes the initial and final angles. + +void CTaskSearch::InitAngle() +{ + int i; + + if ( m_hand == TSH_UP ) + { + m_finalAngle[0] = 110.0f*PI/180.0f; // arm + m_finalAngle[1] = -110.0f*PI/180.0f; // forearm + m_finalAngle[2] = -65.0f*PI/180.0f; // sensor + } + if ( m_hand == TSH_DOWN ) + { + m_finalAngle[0] = 25.0f*PI/180.0f; // arm + m_finalAngle[1] = -70.0f*PI/180.0f; // forearm + m_finalAngle[2] = -45.0f*PI/180.0f; // sensor + } + + for ( i=0 ; i<3 ; i++ ) + { + m_initialAngle[i] = m_object->RetAngleZ(i+1); + } +} + + +// Assigns the goal was achieved. + +Error CTaskSearch::Start() +{ + ObjectType type; + D3DVECTOR speed; + int i; + + m_bError = TRUE; + if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_SEARCH_MOTOR; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH; + + m_hand = TSH_DOWN; + m_phase = TSP_DOWN; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_lastParticule = 0.0f; + + InitAngle(); + m_bError = FALSE; // ok + + m_camera->StartCentering(m_object, PI*0.50f, 99.9f, 0.0f, 1.0f); + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP); + + m_physics->SetFreeze(TRUE); // it does not move + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskSearch::IsEnded() +{ + int i; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TSP_DOWN || + m_phase == TSP_UP ) + { + for ( i=0 ; i<3 ; i++ ) + { + m_object->SetAngleZ(i+1, m_finalAngle[i]); + } + } + + if ( m_phase == TSP_DOWN ) + { + m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0)); + + m_phase = TSP_SEARCH; + m_speed = 1.0f/4.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TSP_SEARCH ) + { + CreateMark(); + + m_hand = TSH_UP; + InitAngle(); + + i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, TRUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP); + + m_phase = TSP_UP; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskSearch::Abort() +{ + m_camera->StopCentering(m_object, 2.0f); + m_physics->SetFreeze(FALSE); // is moving again + return TRUE; +} + + +// Creates a mark if possible. + +BOOL CTaskSearch::CreateMark() +{ + CObject* fret; + ObjectType type; + D3DMATRIX* mat; + D3DVECTOR pos; + TerrainRes res; + Error info; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(7.5f, 0.0f, 0.0f); + pos = Transform(*mat, pos); // sensor position + + res = m_terrain->RetResource(pos); + if ( res == TR_NULL ) return FALSE; + + type = OBJECT_NULL; + if ( res == TR_STONE ) + { + type = OBJECT_MARKSTONE; + info = INFO_MARKSTONE; + } + if ( res == TR_URANIUM ) + { + type = OBJECT_MARKURANIUM; + info = INFO_MARKURANIUM; + } + if ( res == TR_POWER ) + { + type = OBJECT_MARKPOWER; + info = INFO_MARKPOWER; + } + if ( res == TR_KEYa ) + { + type = OBJECT_MARKKEYa; + info = INFO_MARKKEYa; + } + if ( res == TR_KEYb ) + { + type = OBJECT_MARKKEYb; + info = INFO_MARKKEYb; + } + if ( res == TR_KEYc ) + { + type = OBJECT_MARKKEYc; + info = INFO_MARKKEYc; + } + if ( res == TR_KEYd ) + { + type = OBJECT_MARKKEYd; + info = INFO_MARKKEYd; + } + if ( type == OBJECT_NULL ) return FALSE; + +//? DeleteMark(type); + + fret = new CObject(m_iMan); + if ( !fret->CreateResource(pos, 0.0f, type) ) + { + delete fret; + m_displayText->DisplayError(ERR_TOOMANY, m_object); + return FALSE; + } + + m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message + + return TRUE; +} + +// Destroys the marks of a given type. + +void CTaskSearch::DeleteMark(ObjectType type) +{ + CObject* pObj; + D3DVECTOR oPos; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( type == pObj->RetType() ) + { + pObj->DeleteObject(); // removes the mark + delete pObj; + break; + } + } +} + + diff --git a/src/object/task/tasksearch.h b/src/object/task/tasksearch.h new file mode 100644 index 0000000..80970e1 --- /dev/null +++ b/src/object/task/tasksearch.h @@ -0,0 +1,79 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// tasksearch.h + +#ifndef _TASKSEARCH_H_ +#define _TASKSEARCH_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskSearchHand +{ + TSH_UP = 1, // sensor at the top + TSH_DOWN = 2, // sensor at the bottom +}; + +enum TaskSearchPhase +{ + TSP_DOWN = 1, // descends + TSP_SEARCH = 2, // seeks + TSP_UP = 3, // rises +}; + + + +class CTaskSearch : public CTask +{ +public: + CTaskSearch(CInstanceManager* iMan, CObject* object); + ~CTaskSearch(); + + BOOL EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + BOOL Abort(); + +protected: + void InitAngle(); + BOOL CreateMark(); + void DeleteMark(ObjectType type); + +protected: + TaskSearchHand m_hand; + TaskSearchPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_lastParticule; + float m_initialAngle[3]; + float m_finalAngle[3]; + BOOL m_bError; +}; + + +#endif //_TASKSEARCH_H_ diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp new file mode 100644 index 0000000..9269c4b --- /dev/null +++ b/src/object/task/taskshield.cpp @@ -0,0 +1,573 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskshield.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "camera.h" +#include "light.h" +#include "sound.h" +#include "task.h" +#include "taskshield.h" + + +#define ENERGY_TIME 20.0f // maximum duration if full battery + + + +// Object's constructor. + +CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_rankSphere = -1; + m_soundChannel = -1; + m_effectLight = -1; +} + +// Object's destructor. + +CTaskShield::~CTaskShield() +{ + Abort(); +} + + +// Management of an event. + +BOOL CTaskShield::EventProcess(const Event &event) +{ + CObject* power; + D3DMATRIX* mat; + D3DMATRIX matrix; + D3DVECTOR pos, speed, goal, angle; + D3DCOLORVALUE color; + FPOINT dim; + float energy; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + m_delay -= event.rTime; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(7.0f, 15.0f, 0.0f); + pos = Transform(*mat, pos); // sphere position + m_shieldPos = pos; + + if ( m_rankSphere != -1 ) + { + m_particule->SetPosition(m_rankSphere, m_shieldPos); + dim.x = RetRadius(); + dim.y = dim.x; + m_particule->SetDimension(m_rankSphere, dim); + } + + if ( m_phase == TS_UP1 ) + { + pos.x = 7.0f; + pos.y = 4.5f+Bounce(m_progress)*3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + if ( m_phase == TS_UP2 ) + { + pos.x = 0.0f; + pos.y = 1.0f+Bounce(m_progress)*3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + } + + if ( m_phase == TS_SHIELD ) + { + energy = (1.0f/ENERGY_TIME)*event.rTime; + energy *= RetRadius()/RADIUS_SHIELD_MAX; + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity()); + } + m_energyUsed += energy; + + if ( m_soundChannel == -1 ) + { + m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP); + } + else + { + m_sound->Position(m_soundChannel, m_shieldPos); + } + + pos = m_shieldPos; + pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f); + if ( m_effectLight == -1 ) + { + CreateLight(pos); + } + else + { + m_light->SetLightPos(m_effectLight, pos); + + color.r = 0.0f+sinf(m_time*33.2f)*0.2f; + color.g = 0.5f+sinf(m_time*20.0f)*0.5f; + color.b = 0.5f+sinf(m_time*21.3f)*1.0f; + color.a = 0.0f; + m_light->SetLightColor(m_effectLight, color); + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_shieldPos; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = (Rand()-0.5f)*0.0f; + speed.z = (Rand()-0.5f)*0.0f; + speed.y = Rand()*15.0f; + dim.x = Rand()*6.0f+4.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); + } + + if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastRay = m_time; + + pos = m_shieldPos; + dim.x = RetRadius()/20.0f; + dim.y = dim.x; + angle.x = (Rand()-0.5f)*PI*1.2f; + angle.y = 0.0f; + angle.z = (Rand()-0.5f)*PI*1.2f; + MatRotateXZY(matrix, angle); + goal = Transform(matrix, D3DVECTOR(0.0f, RetRadius()-dim.x, 0.0f)); + goal += pos; + m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f); + } + + if ( m_lastIncrease+0.2f <= m_time ) + { + m_lastIncrease = m_time; + IncreaseShield(); + } + } + + if ( m_phase == TS_SMOKE ) + { + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP); + m_soundChannel = -1; + } + + if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time ) + { + m_lastParticule = m_time; + + pos = m_shieldPos; + pos.x += (Rand()-0.5f)*5.0f; + pos.z += (Rand()-0.5f)*5.0f; + speed.x = (Rand()-0.5f)*3.0f; + speed.z = (Rand()-0.5f)*3.0f; + speed.y = (Rand()-0.5f)*3.0f; + dim.x = Rand()*1.5f+2.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f); + } + } + + if ( m_phase == TS_DOWN1 ) + { + pos.x = 0.0f; + pos.y = 1.0f+(1.0f-Bounce(m_progress))*3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + } + + if ( m_phase == TS_DOWN2 ) + { + pos.x = 7.0f; + pos.y = 4.5f+(1.0f-Bounce(m_progress))*3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + return TRUE; +} + + +// Deploys the shield. +// The period is only useful with TSM_UP! + +Error CTaskShield::Start(TaskShieldMode mode, float delay) +{ + CObject* power; + D3DMATRIX* mat; + D3DVECTOR pos, iPos, oPos, speed; + ObjectType type; + float energy; + + if ( mode == TSM_DOWN ) + { + return Stop(); + } + + if ( mode == TSM_UPDATE ) + { + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_OK; + } + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_SHIELD_ENERGY; + energy = power->RetEnergy(); + if ( energy == 0.0f ) return ERR_SHIELD_ENERGY; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(7.0f, 15.0f, 0.0f); + pos = Transform(*mat, pos); // sphere position + m_shieldPos = pos; + + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f); + + m_phase = TS_UP1; + m_progress = 0.0f; + m_speed = 1.0f/1.0f; + m_time = 0.0f; + m_delay = delay; + m_lastParticule = 0.0f; + m_lastRay = 0.0f; + m_lastIncrease = 0.0f; + m_energyUsed = 0.0f; + + m_bError = FALSE; // ok + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } +//? m_camera->StartCentering(m_object, PI*0.85f, -PI*0.15f, RetRadius()+40.0f, 3.0f); + return ERR_OK; +} + +// Returns the shield. + +Error CTaskShield::Stop() +{ + float time; + + if ( m_phase == TS_SHIELD ) + { + m_object->SetShieldRadius(0.0f); + + if ( m_rankSphere != -1 ) + { + m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f); + m_rankSphere = -1; + } + + if ( m_effectLight != -1 ) + { + m_light->DeleteLight(m_effectLight); + m_effectLight = -1; + } + + time = m_energyUsed*4.0f; + if ( time < 1.0f ) time = 1.0f; + if ( time > 4.0f ) time = 4.0f; + + m_phase = TS_SMOKE; + m_speed = 1.0f/time; + + m_camera->StopCentering(m_object, 4.0f); + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_CONTINUE; + } + + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskShield::IsEnded() +{ + CObject* power; + D3DVECTOR pos, speed; + FPOINT dim; + float energy; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_phase == TS_SHIELD ) + { + m_object->SetShieldRadius(RetRadius()); + + power = m_object->RetPower(); + if ( power == 0 ) + { + energy = 0.0f; + } + else + { + energy = power->RetEnergy(); + } + + if ( energy == 0.0f || m_delay <= 0.0f ) + { + Stop(); + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TS_UP1 ) + { + pos.x = 7.0f; + pos.y = 4.5f+3.0f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f); + + m_phase = TS_UP2; + m_speed = 1.0f/0.8f; + return ERR_CONTINUE; + } + + if ( m_phase == TS_UP2 ) + { + pos.x = 0.0f; + pos.y = 1.0f+3.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + + m_object->SetShieldRadius(RetRadius()); + + pos = m_shieldPos; + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = RetRadius(); + dim.y = dim.x; + m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f); + + m_phase = TS_SHIELD; + m_speed = 1.0f/999.9f; + + if ( m_object->RetSelect() ) + { + m_brain->UpdateInterface(); + } + return ERR_CONTINUE; + } + + if ( m_phase == TS_SMOKE ) + { + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f); + + m_phase = TS_DOWN1; + m_speed = 1.0f/0.8f; + return ERR_CONTINUE; + } + + if ( m_phase == TS_DOWN1 ) + { + m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f); + + m_phase = TS_DOWN2; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Indicates whether the action is pending. + +BOOL CTaskShield::IsBusy() +{ + if ( m_phase == TS_SHIELD ) + { + return FALSE; + } + + return TRUE; +} + +// Suddenly ends the current action. + +BOOL CTaskShield::Abort() +{ + D3DVECTOR pos; + + m_object->SetShieldRadius(0.0f); + + pos.x = 7.0f; + pos.y = 4.5f; + pos.z = 0.0f; + m_object->SetPosition(2, pos); + + pos.x = 0.0f; + pos.y = 1.0f; + pos.z = 0.0f; + m_object->SetPosition(3, pos); + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP); + m_soundChannel = -1; + } + + if ( m_rankSphere != -1 ) + { + m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f); + m_rankSphere = -1; + } + + if ( m_effectLight != -1 ) + { + m_light->DeleteLight(m_effectLight); + m_effectLight = -1; + } + + m_camera->StopCentering(m_object, 2.0f); + return TRUE; +} + + +// Creates the light to accompany a pyrotechnic effect. + +BOOL CTaskShield::CreateLight(D3DVECTOR pos) +{ + D3DLIGHT7 light; + + if ( !m_engine->RetLightMode() ) return TRUE; + + ZeroMemory( &light, sizeof(light) ); + light.dltType = D3DLIGHT_SPOT; + light.dcvDiffuse.r = 0.0f; + light.dcvDiffuse.g = 1.0f; + light.dcvDiffuse.b = 2.0f; + light.dvPosition.x = pos.x; + light.dvPosition.y = pos.y; + light.dvPosition.z = pos.z; + light.dvDirection.x = 0.0f; + light.dvDirection.y = -1.0f; // against the bottom + light.dvDirection.z = 0.0f; + light.dvRange = D3DLIGHT_RANGE_MAX; + light.dvFalloff = 1.0f; + light.dvAttenuation0 = 1.0f; + light.dvAttenuation1 = 0.0f; + light.dvAttenuation2 = 0.0f; + light.dvTheta = 0.0f; + light.dvPhi = PI/4.0f; + + m_effectLight = m_light->CreateLight(); + if ( m_effectLight == -1 ) return FALSE; + + m_light->SetLight(m_effectLight, light); + m_light->SetLightIntensity(m_effectLight, 1.0f); + + return TRUE; +} + + +// Repaired the shielded objects within the sphere of the shield. + +void CTaskShield::IncreaseShield() +{ + ObjectType type; + CObject* pObj; + D3DVECTOR oPos; + float dist, shield; + int i; + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, m_shieldPos); + if ( dist <= RetRadius()+10.0f ) + { + shield = pObj->RetShield(); + shield += 0.1f; + if ( shield > 1.0f ) shield = 1.0f; + pObj->SetShield(shield); + } + } +} + + +// Returns the radius of the shield. + +float CTaskShield::RetRadius() +{ + return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam(); +} + + + diff --git a/src/object/task/taskshield.h b/src/object/task/taskshield.h new file mode 100644 index 0000000..8ec2d05 --- /dev/null +++ b/src/object/task/taskshield.h @@ -0,0 +1,94 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskshield.h + +#ifndef _TASKSHIELD_H_ +#define _TASKSHIELD_H_ + + +#include "misc.h" +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +#define RADIUS_SHIELD_MIN 40.0f // minimal radius of the protected zone +#define RADIUS_SHIELD_MAX 100.0f // maximal radius of the protected zone + + +enum TaskShieldPhase +{ + TS_UP1 = 1, // up + TS_UP2 = 2, // up + TS_SHIELD = 3, // shield deployed + TS_SMOKE = 4, // smoke + TS_DOWN1 = 5, // down + TS_DOWN2 = 6, // down +}; + +enum TaskShieldMode +{ + TSM_UP = 1, // deploys shield + TSM_DOWN = 2, // returns the shield + TSM_UPDATE = 3, // radius change +}; + + + +class CTaskShield : public CTask +{ +public: + CTaskShield(CInstanceManager* iMan, CObject* object); + ~CTaskShield(); + + BOOL EventProcess(const Event &event); + + Error Start(TaskShieldMode mode, float delay); + Error IsEnded(); + BOOL IsBusy(); + BOOL Abort(); + +protected: + Error Stop(); + BOOL CreateLight(D3DVECTOR pos); + void IncreaseShield(); + float RetRadius(); + +protected: + TaskShieldPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_delay; + float m_lastParticule; + float m_lastRay; + float m_lastIncrease; + float m_energyUsed; + BOOL m_bError; + D3DVECTOR m_shieldPos; + int m_rankSphere; + int m_soundChannel; + int m_effectLight; +}; + + +#endif //_TASKSHIELD_H_ diff --git a/src/object/task/taskspiderexplo.cpp b/src/object/task/taskspiderexplo.cpp new file mode 100644 index 0000000..b655fe6 --- /dev/null +++ b/src/object/task/taskspiderexplo.cpp @@ -0,0 +1,124 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskspiderexplo.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "object.h" +#include "physics.h" +#include "pyro.h" +#include "motion.h" +#include "motionspider.h" +#include "task.h" +#include "taskspiderexplo.h" + + + + +// Object's constructor. + +CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_time = 0.0f; + m_bError = FALSE; +} + +// Object's destructor. + +CTaskSpiderExplo::~CTaskSpiderExplo() +{ +} + + +// Management of an event. + +BOOL CTaskSpiderExplo::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_bError = TRUE; + return TRUE; + } + + m_time += event.rTime; + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskSpiderExplo::Start() +{ + m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal + m_time = 0.0f; + + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + + m_bError = FALSE; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskSpiderExplo::IsEnded() +{ + CPyro* pyro; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + Abort(); + return ERR_STOP; + } + + if ( m_time < 1.0f ) return ERR_CONTINUE; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide) + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskSpiderExplo::Abort() +{ + return TRUE; +} + diff --git a/src/object/task/taskspiderexplo.h b/src/object/task/taskspiderexplo.h new file mode 100644 index 0000000..fb7f5f6 --- /dev/null +++ b/src/object/task/taskspiderexplo.h @@ -0,0 +1,53 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskspiderexplo.h + +#ifndef _TASKSPIDEREXPLO_H_ +#define _TASKSPIDEREXPLO_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskSpiderExplo : public CTask +{ +public: + CTaskSpiderExplo(CInstanceManager* iMan, CObject* object); + ~CTaskSpiderExplo(); + + BOOL EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + BOOL Abort(); + +protected: + +protected: + float m_time; + BOOL m_bError; +}; + + +#endif //_TASKSPIDEREXPLO_H_ diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp new file mode 100644 index 0000000..35de2b7 --- /dev/null +++ b/src/object/task/tasktake.cpp @@ -0,0 +1,612 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// tasktake.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "water.h" +#include "camera.h" +#include "motion.h" +#include "motionhuman.h" +#include "sound.h" +#include "robotmain.h" +#include "task.h" +#include "tasktake.h" + + + + +// Object's constructor. + +CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + + m_arm = TTA_NEUTRAL; +} + +// Object's destructor. + +CTaskTake::~CTaskTake() +{ +} + + +// Management of an event. + +BOOL CTaskTake::EventProcess(const Event &event) +{ + float a, g, cirSpeed; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + if ( m_bTurn ) // preliminary rotation? + { + a = m_object->RetAngleY(0); + g = m_angle; + cirSpeed = Direction(a, g)*2.0f; + if ( cirSpeed > 1.0f ) cirSpeed = 1.0f; + if ( cirSpeed < -1.0f ) cirSpeed = -1.0f; + + m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right + return TRUE; + } + + m_progress += event.rTime*m_speed; // others advance + + m_physics->SetMotorSpeed(D3DVECTOR(0.0f, 0.0f, 0.0f)); // immobile! + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskTake::Start() +{ + ObjectType type; + CObject* other; + float iAngle, oAngle, h; + D3DVECTOR pos; + + m_height = 0.0f; + m_step = 0; + m_progress = 0.0f; + + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + oAngle = iAngle; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) + { + pos = m_object->RetPosition(0); + h = m_water->RetLevel(m_object); + if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water + return ERR_MANIP_FLY; + } + + type = m_object->RetType(); + if ( type != OBJECT_HUMAN && + type != OBJECT_TECH ) return ERR_MANIP_VEH; + + m_physics->SetMotorSpeed(D3DVECTOR(0.0f, 0.0f, 0.0f)); + + if ( m_object->RetFret() == 0 ) + { + m_order = TTO_TAKE; + } + else + { + m_order = TTO_DEPOSE; + } + + if ( m_order == TTO_TAKE ) + { + pos = m_object->RetPosition(0); + h = m_water->RetLevel(m_object); + if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water + + other = SearchFriendObject(oAngle, 1.5f, PI*0.50f); + if ( other != 0 && other->RetPower() != 0 ) + { + type = other->RetPower()->RetType(); + if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO; + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) return ERR_MANIP_FRIEND; +//? m_camera->StartCentering(m_object, PI*0.3f, -PI*0.1f, 0.0f, 0.8f); + m_arm = TTA_FRIEND; + } + else + { + other = SearchTakeObject(oAngle, 1.5f, PI*0.45f); + if ( other == 0 ) return ERR_MANIP_NIL; + type = other->RetType(); + if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO; +//? m_camera->StartCentering(m_object, PI*0.3f, 99.9f, 0.0f, 0.8f); + m_arm = TTA_FFRONT; + m_main->HideDropZone(other); // hides buildable area + } + } + + if ( m_order == TTO_DEPOSE ) + { +//? speed = m_physics->RetMotorSpeed(); +//? if ( speed.x != 0.0f || +//? speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + other = SearchFriendObject(oAngle, 1.5f, PI*0.50f); + if ( other != 0 && other->RetPower() == 0 ) + { +//? m_camera->StartCentering(m_object, PI*0.3f, -PI*0.1f, 0.0f, 0.8f); + m_arm = TTA_FRIEND; + } + else + { + if ( !IsFreeDeposeObject(D3DVECTOR(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC; +//? m_camera->StartCentering(m_object, PI*0.3f, 99.9f, 0.0f, 0.8f); + m_arm = TTA_FFRONT; + } + } + + m_bTurn = TRUE; // preliminary rotation necessary + m_angle = oAngle; // angle was reached + + m_physics->SetFreeze(TRUE); // it does not move + + m_bError = FALSE; // ok + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTake::IsEnded() +{ + CObject* fret; + float angle; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_bTurn ) // preliminary rotation? + { + angle = m_object->RetAngleY(0); + angle = NormAngle(angle); // 0..2*PI + + if ( TestAngle(angle, m_angle-PI*0.01f, m_angle+PI*0.01f) ) + { + m_bTurn = FALSE; // rotation ended + m_physics->SetMotorSpeedZ(0.0f); + + if ( m_arm == TTA_FFRONT ) + { + m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease + } + if ( m_arm == TTA_FRIEND ) + { + if ( m_height <= 3.0f ) + { + m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease + } + else + { + m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease + } + } + m_progress = 0.0f; + m_speed = 1.0f/0.6f; + } + return ERR_CONTINUE; + } + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + m_step ++; + + if ( m_order == TTO_TAKE ) + { + if ( m_step == 1 ) + { + if ( TruckTakeObject() ) + { + if ( m_arm == TTA_FRIEND && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0)); + } + } + m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up + m_progress = 0.0f; + m_speed = 1.0f/0.8f; + m_camera->StopCentering(m_object, 0.8f); + return ERR_CONTINUE; + } + } + + if ( m_order == TTO_DEPOSE ) + { + if ( m_step == 1 ) + { + fret = m_object->RetFret(); + TruckDeposeObject(); + if ( m_arm == TTA_FRIEND && + (m_fretType == OBJECT_POWER || + m_fretType == OBJECT_ATOMIC ) ) + { + m_sound->Play(SOUND_POWERON, m_object->RetPosition(0)); + } + if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT ) + { + m_main->ShowDropZone(fret, m_object); // shows buildable area + } + m_motion->SetAction(-1); // gets up + m_progress = 0.0f; + m_speed = 1.0f/0.4f; + m_camera->StopCentering(m_object, 0.8f); + return ERR_CONTINUE; + } + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskTake::Abort() +{ + m_motion->SetAction(-1); + m_camera->StopCentering(m_object, 0.8f); + m_physics->SetFreeze(FALSE); // is moving again + return TRUE; +} + + +// Seeks the object to take in front. + +CObject* CTaskTake::SearchTakeObject(float &angle, + float dLimit, float aLimit) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float min, iAngle, bAngle, a, distance; + int i; + + iPos = m_object->RetPosition(0); + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + min = 1000000.0f; + pBest = 0; + bAngle = 0.0f; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + + if ( type != OBJECT_FRET && + type != OBJECT_STONE && + type != OBJECT_URANIUM && + type != OBJECT_BULLET && + type != OBJECT_METAL && + type != OBJECT_POWER && + type != OBJECT_ATOMIC && + type != OBJECT_BBOX && + type != OBJECT_KEYa && + type != OBJECT_KEYb && + type != OBJECT_KEYc && + type != OBJECT_KEYd && + type != OBJECT_TNT ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( pObj->RetLock() ) continue; + if ( pObj->RetZoomY(0) != 1.0f ) continue; + + oPos = pObj->RetPosition(0); + distance = Length(oPos, iPos); + if ( distance >= 4.0f-dLimit && + distance <= 4.0f+dLimit ) + { + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + a = Abs(angle-iAngle); + if ( a > PI ) a = PI*2.0f-a; + if ( a < min ) + { + min = a; + pBest = pObj; + bAngle = angle; + } + } + } + } + angle = bAngle; + return pBest; +} + +// Seeks the robot on which you want take or put a battery. + +CObject* CTaskTake::SearchFriendObject(float &angle, + float dLimit, float aLimit) +{ + Character* character; + CObject* pObj; + CObject* pPower; + D3DMATRIX* mat; + D3DVECTOR iPos, oPos; + ObjectType type, powerType; + float iAngle, iRad, distance; + int i; + + if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0; + iAngle = m_object->RetAngleY(0); + iAngle = NormAngle(iAngle); // 0..2*PI + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; // yourself? + + type = pObj->RetType(); + if ( type != OBJECT_MOBILEfa && + type != OBJECT_MOBILEta && + type != OBJECT_MOBILEwa && + type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfc && + type != OBJECT_MOBILEtc && + type != OBJECT_MOBILEwc && + type != OBJECT_MOBILEic && + type != OBJECT_MOBILEfi && + type != OBJECT_MOBILEti && + type != OBJECT_MOBILEwi && + type != OBJECT_MOBILEii && + type != OBJECT_MOBILEfs && + type != OBJECT_MOBILEts && + type != OBJECT_MOBILEws && + type != OBJECT_MOBILEis && + type != OBJECT_MOBILErt && + type != OBJECT_MOBILErc && + type != OBJECT_MOBILErr && + type != OBJECT_MOBILErs && + type != OBJECT_MOBILEsa && + type != OBJECT_MOBILEtg && + type != OBJECT_MOBILEft && + type != OBJECT_MOBILEtt && + type != OBJECT_MOBILEwt && + type != OBJECT_MOBILEit && + type != OBJECT_TOWER && + type != OBJECT_RESEARCH && + type != OBJECT_ENERGY && + type != OBJECT_LABO && + type != OBJECT_NUCLEAR ) continue; + + pPower = pObj->RetPower(); + if ( pPower != 0 ) + { + if ( pPower->RetLock() ) continue; + if ( pPower->RetZoomY(0) != 1.0f ) continue; + + powerType = pPower->RetType(); + if ( powerType == OBJECT_NULL || + powerType == OBJECT_FIX ) continue; + } + + mat = pObj->RetWorldMatrix(0); + character = pObj->RetCharacter(); + oPos = Transform(*mat, character->posPower); + + distance = Abs(Length(oPos, iPos) - (iRad+1.0f)); + if ( distance <= dLimit ) + { + angle = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) + { + character = pObj->RetCharacter(); + m_height = character->posPower.y; + return pObj; + } + } + } + + return 0; +} + +// Takes the object in front. + +BOOL CTaskTake::TruckTakeObject() +{ + CObject* fret; + CObject* other; + D3DMATRIX matRotate; + float angle; + + if ( m_arm == TTA_FFRONT ) // takes on the ground in front? + { +//? fret = SearchTakeObject(angle, 1.5f, PI*0.04f); + fret = SearchTakeObject(angle, 1.5f, PI*0.15f); //OK 1.9 + if ( fret == 0 ) return FALSE; // rien � prendre ? + m_fretType = fret->RetType(); + + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + +//? fret->SetPosition(0, D3DVECTOR(2.2f, -1.0f, 1.1f)); + fret->SetPosition(0, D3DVECTOR(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + + m_object->SetFret(fret); // takes + } + + if ( m_arm == TTA_FRIEND ) // takes friend's battery? + { + other = SearchFriendObject(angle, 1.5f, PI*0.04f); + if ( other == 0 ) return FALSE; + + fret = other->RetPower(); + if ( fret == 0 ) return FALSE; // the other does not have a battery? + m_fretType = fret->RetType(); + + other->SetPower(0); + fret->SetTruck(m_object); + fret->SetTruckPart(4); // takes with the hand + +//? fret->SetPosition(0, D3DVECTOR(2.2f, -1.0f, 1.1f)); + fret->SetPosition(0, D3DVECTOR(1.7f, -0.5f, 1.1f)); + fret->SetAngleY(0, 0.1f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.8f); + + m_object->SetFret(fret); // takes + } + + return TRUE; +} + +// Deposes the object taken. + +BOOL CTaskTake::TruckDeposeObject() +{ + Character* character; + CObject* fret; + CObject* other; + D3DMATRIX* mat; + D3DVECTOR pos; + float angle; + + if ( m_arm == TTA_FFRONT ) // deposes on the ground in front? + { + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; // does nothing? + m_fretType = fret->RetType(); + + mat = fret->RetWorldMatrix(0); + pos = Transform(*mat, D3DVECTOR(-0.5f, 1.0f, 0.0f)); + m_terrain->MoveOnFloor(pos); + fret->SetPosition(0, pos); + fret->SetAngleY(0, m_object->RetAngleY(0)+PI/2.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->FloorAdjust(); // plate well on the ground + + fret->SetTruck(0); + m_object->SetFret(0); // deposit + } + + if ( m_arm == TTA_FRIEND ) // deposes battery on friends? + { + other = SearchFriendObject(angle, 1.5f, PI*0.04f); + if ( other == 0 ) return FALSE; + + fret = other->RetPower(); + if ( fret != 0 ) return FALSE; // the other already has a battery? + + fret = m_object->RetFret(); + if ( fret == 0 ) return FALSE; + m_fretType = fret->RetType(); + + other->SetPower(fret); + fret->SetTruck(other); + + character = other->RetCharacter(); + fret->SetPosition(0, character->posPower); + fret->SetAngleY(0, 0.0f); + fret->SetAngleX(0, 0.0f); + fret->SetAngleZ(0, 0.0f); + fret->SetTruckPart(0); // carried by the base + + m_object->SetFret(0); // deposit + } + + return TRUE; +} + +// Seeks if a location allows to deposit an object. + +BOOL CTaskTake::IsFreeDeposeObject(D3DVECTOR pos) +{ + CObject* pObj; + D3DMATRIX* mat; + D3DVECTOR iPos, oPos; + float oRadius; + int i, j; + + mat = m_object->RetWorldMatrix(0); + iPos = Transform(*mat, pos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj == m_object ) continue; + if ( !pObj->RetActif() ) continue; // inactive? + if ( pObj->RetTruck() != 0 ) continue; // object transported? + + j = 0; + while ( pObj->GetCrashSphere(j++, oPos, oRadius) ) + { + if ( Length(iPos, oPos)-(oRadius+1.0f) < 1.0f ) + { + return FALSE; // location occupied + } + } + } + return TRUE; // location free +} + + diff --git a/src/object/task/tasktake.h b/src/object/task/tasktake.h new file mode 100644 index 0000000..80b8736 --- /dev/null +++ b/src/object/task/tasktake.h @@ -0,0 +1,85 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// tasktake.h + +#ifndef _TASKTAKE_H_ +#define _TASKTAKE_H_ + + +#include "misc.h" +#include "object.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskTakeOrder +{ + TTO_TAKE = 1, // takes an object + TTO_DEPOSE = 2, // deposes the object +}; + +enum TaskTakeArm +{ + TTA_NEUTRAL = 1, // empty arm at rest + TTA_FFRONT = 2, // arm on the ground + TTA_FRIEND = 3, // arm behind a friend robot +}; + + + +class CTaskTake : public CTask +{ +public: + CTaskTake(CInstanceManager* iMan, CObject* object); + ~CTaskTake(); + + BOOL EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + BOOL Abort(); + +protected: + CObject* SearchTakeObject(float &angle, float dLimit, float aLimit); + CObject* SearchFriendObject(float &angle, float dLimit, float aLimit); + BOOL TruckTakeObject(); + BOOL TruckDeposeObject(); + BOOL IsFreeDeposeObject(D3DVECTOR pos); + +protected: + CTerrain* m_terrain; + + TaskTakeOrder m_order; + TaskTakeArm m_arm; + int m_step; + float m_speed; + float m_progress; + float m_height; + BOOL m_bError; + BOOL m_bTurn; + float m_angle; + ObjectType m_fretType; +}; + + +#endif //_TASKTAKE_H_ diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp new file mode 100644 index 0000000..e2f75fc --- /dev/null +++ b/src/object/task/taskterraform.cpp @@ -0,0 +1,429 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskterraform.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "language.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "particule.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "pyro.h" +#include "brain.h" +#include "camera.h" +#include "sound.h" +#include "motion.h" +#include "motionant.h" +#include "motionspider.h" +#include "task.h" +#include "taskterraform.h" + + +#define ENERGY_TERRA 0.40f // energy consumed by blow +#define ACTION_RADIUS 400.0f + + + +// Object's constructor. + +CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); + m_lastParticule = 0.0f; + m_soundChannel = -1; +} + +// Object's destructor. + +CTaskTerraform::~CTaskTerraform() +{ +} + + +// Management of an event. + +BOOL CTaskTerraform::EventProcess(const Event &event) +{ + CObject* power; + D3DMATRIX* mat; + D3DVECTOR pos, dir, speed; + FPOINT dim; + float energy; + + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + if ( m_bError ) return FALSE; + + m_progress += event.rTime*m_speed; // others advance + m_time += event.rTime; + + if ( m_phase == TTP_CHARGE ) + { + if ( m_soundChannel == -1 ) + { +#if _TEEN + m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP); +#else + m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, TRUE); + m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP); +#endif + } + + dir.x = 0.0f; + dir.y = (Rand()-0.5f)*0.2f*m_progress; + dir.z = 0.0f; + m_object->SetCirVibration(dir); + + m_object->SetZoom(0, 1.0f+m_progress*0.2f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f+m_progress*1.0f); + + energy = power->RetEnergy(); + energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f; + if ( energy < 0.0f ) energy = 0.0f; + power->SetEnergy(energy); + } + } + + if ( m_phase == TTP_DOWN ) + { + pos.x = 9.0f; +#if _TEEN + pos.y = 4.0f-m_progress*4.0f; +#else + pos.y = 4.0f-m_progress*5.8f; +#endif + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + if ( m_phase == TTP_UP ) + { + pos.x = 9.0f; +#if _TEEN + pos.y = 4.0f-(1.0f-m_progress)*4.0f; +#else + pos.y = 4.0f-(1.0f-m_progress)*5.8f; +#endif + pos.z = 0.0f; + m_object->SetPosition(2, pos); + } + + dir.x = 0.0f; + dir.y = 0.0f; + dir.z = 0.0f; + pos = m_object->RetPosition(2); + if ( pos.y < 0.0f ) + { + dir.z = -atanf((pos.y/2.0f)/9.0f); + } + m_object->SetInclinaison(dir); + + if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) ) + { + m_lastParticule = m_time; + + mat = m_object->RetWorldMatrix(0); + + if ( m_phase == TTP_CHARGE ) + { + // Battery. + pos = D3DVECTOR(-6.0f, 5.5f+2.0f*m_progress, 0.0f); + pos.x += (Rand()-0.5f)*1.0f; + pos.z += (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed.x = (Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f); + speed.z = (Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f); + speed.y = 6.0f+Rand()*4.0f*(1.0f+m_progress*2.0f); + dim.x = 0.5f+1.5f*m_progress; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f); + } + + if ( m_phase != TTP_CHARGE ) + { + // Left grid. + pos = D3DVECTOR(-1.0f, 5.8f, 3.5f); + pos.x += (Rand()-0.5f)*1.0f; + pos.z += (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed.x = Rand()*4.0f; + speed.z = Rand()*2.0f; + speed.y = 2.5f+Rand()*1.0f; + speed = Transform(*mat, speed); + speed -= m_object->RetPosition(0); + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + + // Right grid. + pos = D3DVECTOR(-1.0f, 5.8f, -3.5f); + pos.x += (Rand()-0.5f)*1.0f; + pos.z += (Rand()-0.5f)*1.0f; + pos = Transform(*mat, pos); + speed.x = Rand()*4.0f; + speed.z = -Rand()*2.0f; + speed.y = 2.5f+Rand()*1.0f; + speed = Transform(*mat, speed); + speed -= m_object->RetPosition(0); + dim.x = Rand()*1.0f+1.0f; + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f); + } + } + + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskTerraform::Start() +{ + CObject* power; + D3DMATRIX* mat; + D3DVECTOR pos, speed; + float energy; + + ObjectType type; + + m_bError = TRUE; // operation impossible + if ( !m_physics->RetLand() ) return ERR_TERRA_VEH; + + type = m_object->RetType(); + if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH; + + power = m_object->RetPower(); + if ( power == 0 ) return ERR_TERRA_ENERGY; + energy = power->RetEnergy(); + if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY; + + speed = m_physics->RetMotorSpeed(); + if ( speed.x != 0.0f || + speed.z != 0.0f ) return ERR_MANIP_MOTOR; + + mat = m_object->RetWorldMatrix(0); + pos = D3DVECTOR(9.0f, 0.0f, 0.0f); + pos = Transform(*mat, pos); // battery position + m_terraPos = pos; + + m_phase = TTP_CHARGE; + m_progress = 0.0f; +#if _TEEN + m_speed = 1.0f/1.5f; +#else + m_speed = 1.0f/4.0f; +#endif + m_time = 0.0f; + + m_bError = FALSE; // ok + + m_camera->StartCentering(m_object, PI*0.35f, 99.9f, 20.0f, 2.0f); + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTerraform::IsEnded() +{ + CObject* power; + D3DVECTOR pos, speed; + FPOINT dim; + float dist, duration; + int i, max; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bError ) return ERR_STOP; + + if ( m_progress < 1.0f ) return ERR_CONTINUE; + m_progress = 0.0f; + + if ( m_phase == TTP_CHARGE ) + { +#if _TEEN + Terraform(); // changes the terrain. +#endif + + m_phase = TTP_DOWN; + m_speed = 1.0f/0.2f; + return ERR_CONTINUE; + } + + if ( m_phase == TTP_DOWN ) + { +#if !_TEEN + Terraform(); // changes the terrain. +#endif + + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f); + } + + max= (int)(50.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iMoveOnFloor(pos); + dist = Length(pos, m_terraPos); + speed = D3DVECTOR(0.0f, 0.0f, 0.0f); + dim.x = 2.0f+(40.0f-dist)/(1.0f+Rand()*4.0f); + dim.y = dim.x; + m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f); + + pos = m_terraPos; + speed.x = (Rand()-0.5f)*40.0f; + speed.z = (Rand()-0.5f)*40.0f; + speed.y = Rand()*15.0f+15.0f; + dim.x = 0.6f; + dim.y = dim.x; + pos.y += dim.y; + duration = Rand()*3.0f+3.0f; + m_particule->CreateTrack(pos, speed, dim, PARTITRACK5, + duration, Rand()*10.0f+15.0f, + duration*0.2f, 1.0f); + } + + m_phase = TTP_TERRA; + m_speed = 1.0f/2.0f; + return ERR_CONTINUE; + } + + if ( m_phase == TTP_TERRA ) + { + m_phase = TTP_UP; + m_speed = 1.0f/1.0f; + return ERR_CONTINUE; + } + + Abort(); + return ERR_STOP; +} + +// Suddenly ends the current action. + +BOOL CTaskTerraform::Abort() +{ + CObject* power; + + if ( m_soundChannel != -1 ) + { + m_sound->FlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP); + m_soundChannel = -1; + } + + m_object->SetPosition(2, D3DVECTOR(9.0f, 4.0f, 0.0f)); + m_object->SetInclinaison(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetCirVibration(D3DVECTOR(0.0f, 0.0f, 0.0f)); + m_object->SetZoom(0, 1.0f); + + power = m_object->RetPower(); + if ( power != 0 ) + { + power->SetZoom(0, 1.0f); + } + + m_camera->StopCentering(m_object, 2.0f); + return TRUE; +} + + +// Returns all the close ants and spiders. + +BOOL CTaskTerraform::Terraform() +{ + CObject* pObj; + CBrain* brain; + CMotion* motion; + CPyro* pyro; + ObjectType type; + float dist; + int i; + + m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f); + + m_sound->Play(SOUND_THUMP, m_terraPos); + + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type == OBJECT_NULL ) continue; + + if ( type == OBJECT_TEEN34 ) // stone? + { + dist = Length(m_terraPos, pObj->RetPosition(0)); + if ( dist > 20.0f ) continue; + + pyro = new CPyro(m_iMan); + pyro->Create(PT_FRAGT, pObj); + } + else + { + motion = pObj->RetMotion(); + if ( motion == 0 ) continue; + + dist = Length(m_terraPos, pObj->RetPosition(0)); + if ( dist > ACTION_RADIUS ) continue; + + if ( type == OBJECT_ANT ) + { + brain = pObj->RetBrain(); + if ( brain != 0 ) brain->StopTask(); + motion->SetAction(MAS_BACK1, 0.8f+Rand()*0.3f); + pObj->SetFixed(TRUE); // not moving + } + if ( type == OBJECT_SPIDER ) + { + brain = pObj->RetBrain(); + if ( brain != 0 ) brain->StopTask(); + motion->SetAction(MSS_BACK1, 0.8f+Rand()*0.3f); + pObj->SetFixed(TRUE); // not moving + } + } + } + + return TRUE; +} + diff --git a/src/object/task/taskterraform.h b/src/object/task/taskterraform.h new file mode 100644 index 0000000..254e363 --- /dev/null +++ b/src/object/task/taskterraform.h @@ -0,0 +1,72 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskterraform.h + +#ifndef _TASKSTERRAFORM_H_ +#define _TASKSTERRAFORM_H_ + + +#include "misc.h" +#include "d3dengine.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + + +enum TaskTerraPhase +{ + TTP_CHARGE = 1, // charge of energy + TTP_DOWN = 2, // down + TTP_TERRA = 3, // strike + TTP_UP = 4, // up +}; + + + +class CTaskTerraform : public CTask +{ +public: + CTaskTerraform(CInstanceManager* iMan, CObject* object); + ~CTaskTerraform(); + + BOOL EventProcess(const Event &event); + + Error Start(); + Error IsEnded(); + BOOL Abort(); + +protected: + BOOL Terraform(); + +protected: + TaskTerraPhase m_phase; + float m_progress; + float m_speed; + float m_time; + float m_lastParticule; + int m_soundChannel; + BOOL m_bError; + D3DVECTOR m_terraPos; +}; + + +#endif //_TASKSTERRAFORM_H_ diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp new file mode 100644 index 0000000..832f523 --- /dev/null +++ b/src/object/task/taskturn.cpp @@ -0,0 +1,147 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskturn.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "task.h" +#include "taskturn.h" + + + + +// Object's constructor. + +CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskTurn::~CTaskTurn() +{ +} + + +// Management of an event. + +BOOL CTaskTurn::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + // Momentarily stationary object (ant on the back)? + if ( m_object->RetFixed() ) + { + m_physics->SetMotorSpeedX(0.0f); // stops the advance + m_physics->SetMotorSpeedZ(0.0f); // stops the rotation + m_bError = TRUE; + return TRUE; + } + + return TRUE; +} + + +// Assigns the goal was achieved. +// A positive angle is turning right. + +Error CTaskTurn::Start(float angle) +{ + m_startAngle = m_object->RetAngleY(0); + m_finalAngle = m_startAngle+angle; + + if ( angle < 0.0f ) + { + m_angle = angle+m_physics->RetCirStopLength(); + m_physics->SetMotorSpeedZ(-1.0f); // turns left + m_bLeft = TRUE; + } + else + { + m_angle = angle-m_physics->RetCirStopLength(); + m_physics->SetMotorSpeedZ(1.0f); // turns right + m_bLeft = FALSE; + } + m_physics->SetMotorSpeedX(0.0f); + m_physics->SetMotorSpeedY(0.0f); + + m_bError = FALSE; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskTurn::IsEnded() +{ + float angle; + + if ( m_engine->RetPause() ) return ERR_CONTINUE; + + if ( m_bError ) + { + return ERR_STOP; + } + + angle = m_object->RetAngleY(0); + + if ( m_bLeft ) + { + if ( angle <= m_startAngle+m_angle ) + { + m_physics->SetMotorSpeedZ(0.0f); +//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f); + m_physics->SetCirMotionY(MO_CURSPEED, 0.0f); +//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f); + m_object->SetAngleY(0, m_finalAngle); + return ERR_STOP; + } + } + else + { + if ( angle >= m_startAngle+m_angle ) + { + m_physics->SetMotorSpeedZ(0.0f); +//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f); + m_physics->SetCirMotionY(MO_CURSPEED, 0.0f); +//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f); + m_object->SetAngleY(0, m_finalAngle); + return ERR_STOP; + } + } + + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskturn.h b/src/object/task/taskturn.h new file mode 100644 index 0000000..abaef57 --- /dev/null +++ b/src/object/task/taskturn.h @@ -0,0 +1,55 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskturn.h + +#ifndef _TASKTURN_H_ +#define _TASKTURN_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskTurn : public CTask +{ +public: + CTaskTurn(CInstanceManager* iMan, CObject* object); + ~CTaskTurn(); + + BOOL EventProcess(const Event &event); + + Error Start(float angle); + Error IsEnded(); + +protected: + +protected: + float m_angle; + float m_startAngle; + float m_finalAngle; + BOOL m_bLeft; + BOOL m_bError; +}; + + +#endif //_TASKTURN_H_ diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp new file mode 100644 index 0000000..af06383 --- /dev/null +++ b/src/object/task/taskwait.cpp @@ -0,0 +1,89 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskwait.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "struct.h" +#include "d3dengine.h" +#include "math3d.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "terrain.h" +#include "object.h" +#include "physics.h" +#include "brain.h" +#include "task.h" +#include "taskwait.h" + + + + +// Object's constructor. + +CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object) + : CTask(iMan, object) +{ + CTask::CTask(iMan, object); +} + +// Object's destructor. + +CTaskWait::~CTaskWait() +{ +} + + +// Management of an event. + +BOOL CTaskWait::EventProcess(const Event &event) +{ + if ( m_engine->RetPause() ) return TRUE; + if ( event.event != EVENT_FRAME ) return TRUE; + + m_passTime += event.rTime; + m_bEnded = (m_passTime >= m_waitTime); + return TRUE; +} + + +// Assigns the goal was achieved. + +Error CTaskWait::Start(float time) +{ + m_waitTime = time; // duration to wait + m_passTime = 0.0f; // time elapsed + m_bEnded = FALSE; + return ERR_OK; +} + +// Indicates whether the action is finished. + +Error CTaskWait::IsEnded() +{ + if ( m_engine->RetPause() ) return ERR_CONTINUE; + if ( m_bEnded ) return ERR_STOP; + return ERR_CONTINUE; +} + + diff --git a/src/object/task/taskwait.h b/src/object/task/taskwait.h new file mode 100644 index 0000000..e8ba2b6 --- /dev/null +++ b/src/object/task/taskwait.h @@ -0,0 +1,53 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * 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 3 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, see http://www.gnu.org/licenses/. + +// taskwait.h + +#ifndef _TASKWAIT_H_ +#define _TASKWAIT_H_ + + +#include "misc.h" + + +class CInstanceManager; +class CTerrain; +class CBrain; +class CPhysics; +class CObject; + + +class CTaskWait : public CTask +{ +public: + CTaskWait(CInstanceManager* iMan, CObject* object); + ~CTaskWait(); + + BOOL EventProcess(const Event &event); + + Error Start(float time); + Error IsEnded(); + +protected: + +protected: + float m_waitTime; + float m_passTime; + BOOL m_bEnded; +}; + + +#endif //_TASKWAIT_H_ -- cgit v1.2.3-1-g7c22