Skip to content

Commit

Permalink
added commands createUnit, units, deleteGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
X39 committed Aug 25, 2018
1 parent 3f0a935 commit 30af3e0
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 17 deletions.
42 changes: 42 additions & 0 deletions sqfvm-cpp/groupcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include "virtualmachine.h"
#include "sidedata.h"
#include "groupdata.h"
#include "objectdata.h"
#include "innerobj.h"
#include "arraydata.h"
#include <sstream>

using namespace sqf;
Expand All @@ -23,6 +26,42 @@ namespace
auto grp = right->data<groupdata>();
return std::make_shared<value>(grp->groupid());
}
std::shared_ptr<value> units_group(virtualmachine* vm, std::shared_ptr<value> right)
{
auto grp = right->data<groupdata>();
auto arr = std::make_shared<arraydata>();
for (auto it = grp->units_begin(); it != grp->units_end(); it++)
{
arr->push_back(std::make_shared<value>(std::make_shared<objectdata>(*it), OBJECT));
}
return std::make_shared<value>(arr, ARRAY);
}
std::shared_ptr<value> units_object(virtualmachine* vm, std::shared_ptr<value> right)
{
auto grp = right->data<objectdata>()->obj()->group();
auto arr = std::make_shared<arraydata>();
if (grp.get())
{
for (auto it = grp->units_begin(); it != grp->units_end(); it++)
{
arr->push_back(std::make_shared<value>(std::make_shared<objectdata>(*it), OBJECT));
}
}
return std::make_shared<value>(arr, ARRAY);
}
std::shared_ptr<value> deletegroup_group(virtualmachine* vm, std::shared_ptr<value> right)
{
auto grp = right->data<groupdata>();
if (grp->is_empty())
{
vm->drop_group(grp);
}
else
{
vm->wrn() << "Attempt to delete a non-empty group was made. GroupID: " << grp->groupid() << '.' << std::endl;
}
return std::make_shared<value>();
}
}
void sqf::commandmap::initgroupcmds(void)
{
Expand All @@ -43,4 +82,7 @@ void sqf::commandmap::initgroupcmds(void)
add(nular("grpNull", "A non-existing Group. To compare non-existent groups use isNull or isEqualTo.", grpnull_));
add(unary("createGroup", type::SIDE, "Creates a new Group for the given Side.", creategroup_side));
add(unary("groupId", type::GROUP, "Returns group name.", groupid_group));
add(unary("units", type::GROUP, "Returns an array with all the units in the group.", units_group));
add(unary("units", type::OBJECT, "Returns an array with all the units in the group of the unit. For a destroyed object an empty array is returned.", units_object));
add(unary("deleteGroup", type::GROUP, "Destroys the given group. Group must be empty.", deletegroup_group));
}
21 changes: 21 additions & 0 deletions sqfvm-cpp/groupdata.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "groupdata.h"
#include "virtualmachine.h"
#include "innerobj.h"

std::shared_ptr<sqf::groupdata> sqf::groupdata::create(sqf::virtualmachine * vm, std::shared_ptr<sqf::sidedata> side)
{
Expand All @@ -9,3 +10,23 @@ std::shared_ptr<sqf::groupdata> sqf::groupdata::create(sqf::virtualmachine * vm,
vm->push_group(grp);
return grp;
}

void sqf::groupdata::add_unit(std::shared_ptr<innerobj> unit)
{
munits.push_back(unit);
unit->group(shared_from_this());
}

void sqf::groupdata::drop_unit(std::shared_ptr<innerobj> unit)
{
for (size_t i = 0; i < munits.size(); i++)
{
if (unit.get() == munits[i].get())
{
munits[i] = munits.back();
unit->group(std::shared_ptr<groupdata>());
munits.pop_back();
break;
}
}
}
12 changes: 11 additions & 1 deletion sqfvm-cpp/groupdata.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#pragma once
#include <string>
#include <memory>
#include <vector>
#include "data.h"
#include "varscope.h"
#include "sidedata.h"

namespace sqf
{
class virtualmachine;
class groupdata : public data, public varscope
class innerobj;
class groupdata : public data, public varscope, public std::enable_shared_from_this<groupdata>
{
private:
std::vector<std::shared_ptr<innerobj>> munits;
std::shared_ptr<sidedata> mside;
std::string mgroupid;
groupdata(std::shared_ptr<sidedata> side) : mside(side) { }
Expand All @@ -25,7 +28,14 @@ namespace sqf
inline void groupid(std::string id) { mgroupid = id; }
virtual std::string tosqf(void) const { return mgroupid; }

inline std::vector<std::shared_ptr<innerobj>>::iterator units_begin(void) { return munits.begin(); }
inline std::vector<std::shared_ptr<innerobj>>::iterator units_end(void) { return munits.end(); }
inline bool is_empty(void) const { return munits.size() == 0; }

static inline std::shared_ptr<sqf::groupdata> create() { return std::shared_ptr<groupdata>(); }
static std::shared_ptr<sqf::groupdata> create(sqf::virtualmachine* vm, std::shared_ptr<sqf::sidedata> side);

void add_unit(std::shared_ptr<innerobj> unit);
void drop_unit(std::shared_ptr<innerobj> unit);
};
}
5 changes: 5 additions & 0 deletions sqfvm-cpp/innerobj.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "innerobj.h"
#include "virtualmachine.h"
#include "groupdata.h"
#include <sstream>

std::string sqf::innerobj::tosqf(void) const
Expand All @@ -11,6 +12,10 @@ std::string sqf::innerobj::tosqf(void) const

void sqf::innerobj::destroy(sqf::virtualmachine * vm)
{
if (mgroup.get())
{
mgroup->drop_unit(shared_from_this());
}
vm->drop_obj(this);
}

Expand Down
7 changes: 6 additions & 1 deletion sqfvm-cpp/innerobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
namespace sqf
{
class virtualmachine;
class innerobj
class groupdata;
class innerobj : public std::enable_shared_from_this<innerobj>
{
private:
size_t mnetid;
Expand All @@ -17,6 +18,7 @@ namespace sqf
double mvely;
double mvelz;
std::string mclassname;
std::shared_ptr<groupdata> mgroup;

bool misvehicle;
innerobj(std::string classname, bool isvehicle) : mclassname(classname), misvehicle(isvehicle) {}
Expand All @@ -34,6 +36,7 @@ namespace sqf
inline std::string classname(void) const { return mclassname; }
inline size_t netid(void) const { return mnetid; }
inline bool is_vehicle(void) const { return misvehicle; }
inline std::shared_ptr<groupdata> group(void) const { return mgroup; }

inline void pos(std::array<double, 3> arr) { mposx = arr[0]; mposy = arr[1]; mposz = arr[2]; }
inline void posx(double d) { mposx = d; }
Expand All @@ -43,6 +46,8 @@ namespace sqf
inline void velx(double d) { mvelx = d; }
inline void vely(double d) { mvely = d; }
inline void velz(double d) { mvelz = d; }
inline void group(std::shared_ptr<groupdata> g) { mgroup = g; }

void destroy(sqf::virtualmachine*);

static std::shared_ptr<sqf::innerobj> create(sqf::virtualmachine* vm, std::string classname, bool isvehicle);
Expand Down
171 changes: 160 additions & 11 deletions sqfvm-cpp/objectcmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "varscope.h"
#include "arraydata.h"
#include "configdata.h"
#include "groupdata.h"
#include <algorithm>
#include <cstdlib>

Expand Down Expand Up @@ -52,19 +53,10 @@ namespace
return std::make_shared<value>();
}
auto position = arr->at(1)->data<arraydata>();
if (position->size() != 3)
if (!position->check_type(vm, SCALAR, 3))
{
vm->err() << "Element 1 in input array was expected to have 3 elements of type SCALAR. Got " << position->size() << '.' << std::endl;
return std::make_shared<value>();
}
for (size_t i = 0; i < 3; i++)
{
if (position->at(i)->dtype() != SCALAR)
{
vm->err() << "Element " << i << " of input array element 1 was expected to be of type SCALAR. Got " << type_str(position->at(i)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
}
//Markers
if (arr->at(2)->dtype() != ARRAY)
{
Expand Down Expand Up @@ -271,6 +263,162 @@ namespace
}
return std::make_shared<value>();
}

std::shared_ptr<value> createUnit_group_array(virtualmachine* vm, std::shared_ptr<value> left, std::shared_ptr<value> right)
{
auto grp = left->data<groupdata>();
auto arr = right->data<arraydata>();

if (arr->size() != 5)
{
vm->err() << "Array was expected to have exactly 5 elements. Got " << arr->size() << '.' << std::endl;
return std::make_shared<value>();
}
//Type
if (arr->at(0)->dtype() != STRING)
{
vm->err() << "Element 0 in input array was expected to be of type STRING. Got " << type_str(arr->at(0)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
auto type = arr->at(0)->as_string();
//Position
if (arr->at(1)->dtype() != ARRAY)
{
vm->err() << "Element 1 in input array was expected to be of type ARRAY. Got " << type_str(arr->at(0)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
auto position = arr->at(1)->data<arraydata>();
if (!position->check_type(vm, SCALAR, 3))
{
return std::make_shared<value>();
}
//Markers
if (arr->at(2)->dtype() != ARRAY)
{
vm->err() << "Element 2 in input array was expected to be of type ARRAY. Got " << type_str(arr->at(2)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
//Placement Radius
if (arr->at(3)->dtype() != SCALAR)
{
vm->err() << "Element 3 in input array was expected to be of type SCALAR. Got " << type_str(arr->at(2)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
auto radius = arr->at(3)->as_double();
//SPECIAL
if (arr->at(4)->dtype() != STRING)
{
vm->err() << "Element 4 in input array was expected to be of type STRING. Got " << type_str(arr->at(2)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
if (vm->perform_classname_checks())
{
auto configBin = sqf::configdata::configFile()->data<sqf::configdata>();
auto cfgVehicles = configBin->navigate("CfgVehicles");
auto vehConfig = cfgVehicles->data<sqf::configdata>()->navigate(type);
if (vehConfig->data<configdata>()->is_null())
{
vm->wrn() << "The config entry for '" << type << "' could not be located in `ConfigBin >> CfgVehicles`." << std::endl;
return std::make_shared<value>();
}
}
auto veh = innerobj::create(vm, type, false);
grp->add_unit(veh);
veh->posx(position->at(0)->as_double() + ((std::rand() % (int)(radius * 2)) - radius));
veh->posy(position->at(1)->as_double() + ((std::rand() % (int)(radius * 2)) - radius));
veh->posz(position->at(2)->as_double());
return std::make_shared<value>(std::make_shared<objectdata>(veh), OBJECT);
}
std::shared_ptr<value> createUnit_string_array(virtualmachine* vm, std::shared_ptr<value> left, std::shared_ptr<value> right)
{
auto type = left->as_string();
auto arr = right->data<arraydata>();
std::string init = "";
double skill = 0.5;
std::string rank = "PRIVATE";

if (arr->size() < 2)
{
vm->err() << "Array was expected to have at least 2 elements. Got " << arr->size() << '.' << std::endl;
return std::make_shared<value>();
}
//Position
if (arr->at(0)->dtype() != ARRAY)
{
vm->err() << "Element 0 in input array was expected to be of type ARRAY. Got " << type_str(arr->at(0)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
auto position = arr->at(0)->data<arraydata>();
if (!position->check_type(vm, SCALAR, 3))
{
return std::make_shared<value>();
}
//Group
if (arr->at(1)->dtype() != GROUP)
{
vm->err() << "Element 1 in input array was expected to be of type GROUP. Got " << type_str(arr->at(1)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
auto grp = arr->at(1)->data<groupdata>();

//Optionals
//init
if (arr->size() >= 3)
{
if (arr->at(2)->dtype() != STRING)
{
vm->err() << "Element 2 in input array was expected to be of type STRING. Got " << type_str(arr->at(2)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
else
{
init = arr->at(2)->as_string();
}
}
//skill
if (arr->size() >= 4)
{
if (arr->at(3)->dtype() != SCALAR)
{
vm->err() << "Element 3 in input array was expected to be of type SCALAR. Got " << type_str(arr->at(3)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
else
{
skill = arr->at(3)->as_double();
}
}
//rank
if (arr->size() >= 5)
{
if (arr->at(4)->dtype() != STRING)
{
vm->err() << "Element 4 in input array was expected to be of type STRING. Got " << type_str(arr->at(4)->dtype()) << '.' << std::endl;
return std::make_shared<value>();
}
else
{
rank = arr->at(4)->as_double();
}
}
if (vm->perform_classname_checks())
{
auto configBin = sqf::configdata::configFile()->data<sqf::configdata>();
auto cfgVehicles = configBin->navigate("CfgVehicles");
auto vehConfig = cfgVehicles->data<sqf::configdata>()->navigate(type);
if (vehConfig->data<configdata>()->is_null())
{
vm->wrn() << "The config entry for '" << type << "' could not be located in `ConfigBin >> CfgVehicles`." << std::endl;
return std::make_shared<value>();
}
}
auto veh = innerobj::create(vm, type, false);
grp->add_unit(veh);
veh->posx(position->at(0)->as_double());
veh->posy(position->at(1)->as_double());
veh->posz(position->at(2)->as_double());
return std::make_shared<value>(std::make_shared<objectdata>(veh), OBJECT);
}
}
void sqf::commandmap::initobjectcmds(void)
{
Expand All @@ -288,5 +436,6 @@ void sqf::commandmap::initobjectcmds(void)
add(binary(4, "setVelocity", type::OBJECT, type::ARRAY, "Set velocity (speed vector) of a vehicle. Units are in metres per second.", setvelocity_object_array));
add(binary(4, "doMove", type::OBJECT, type::ARRAY, "Order the given unit(s) to move to the given position (without radio messages). In SQFVM this command acts like setPos.", domove_object_array));
add(binary(4, "doMove", type::ARRAY, type::ARRAY, "Order the given unit(s) to move to the given position (without radio messages). In SQFVM this command acts like setPos.", domove_array_array));

add(binary(4, "createUnit", type::GROUP, type::ARRAY, "Create unit of a class that's defined in CfgVehicles.", createUnit_group_array));
add(binary(4, "createUnit", type::STRING, type::ARRAY, "Create unit of a class that's defined in CfgVehicles.", createUnit_string_array));
}

0 comments on commit 30af3e0

Please sign in to comment.