using components for weapons instead of separate nodes

This commit is contained in:
devZoGok
2025-12-06 13:18:02 +02:00
parent 1cfa181918
commit c3b94fdc21
3 changed files with 73 additions and 56 deletions
+12 -8
View File
@@ -173,7 +173,8 @@ units = {
rateOfFire = 1000,
damage = 200,
maxRange = 50,
nodes = {{name = 'Turret', rotationSpeed = .05, maxFireAngle = .1}},
maxFireAngle = .1,
nodes = {{name = 'Turret', rotationSpeed = .05, vertical = false}},
projectile = {id = ProjectileId.HE_SHELL, parent = 'Turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = 1, x = 0, y = 0, z = 0}},
fireFx = {
{
@@ -230,9 +231,10 @@ units = {
rateOfFire = 2000,
damage = 5000,
maxRange = 70,
maxFireAngle = .1,
nodes = {
{name = 'turret', rotationSpeed = .05, maxFireAngle = .1},
{name = 'tubes', rotationSpeed = .05, maxFireAngle = .1}
{name = 'turret', rotationSpeed = .05, vertical = false},
--{name = 'tubes', rotationSpeed = .05, vertical = true}
},
projectile = {id = ProjectileId.MISSILE, parent = 'tubes', pos = {x = 0.95, y = 2.16, z = 4.11}, rot = {w = 1, x = 0, y = 0, z = 0}},
fireFx = {
@@ -896,7 +898,8 @@ units = {
rateOfFire = 1000,
damage = 0,
maxRange = 25,
nodes = {{name = 'turret', rotationSpeed = .05, maxFireAngle = .1}},
maxFireAngle = .1,
nodes = {{name = 'turret', rotationSpeed = .05, vertical = false}},
projectile = {id = ProjectileId.EMP_SHELL, parent = 'turret', pos = {x = 0.06, y = 5.82, z = 11.4}, rot = {w = .998, x = -.066, y = 0, z = 0}},
fireFx = {
{
@@ -1024,11 +1027,12 @@ units = {
{
orderType = OrderType.ATTACK,
rateOfFire = 100,
damage = 50,
maxRange = 50,
damage = 17,
maxRange = 100,
maxFireAngle = .4,
nodes = {
{name = 'TurretBody', rotationSpeed = .05, maxFireAngle = .1},
{name = 'TurretArms', rotationSpeed = .05, maxFireAngle = .1}
{name = 'TurretBody', rotationSpeed = .1, vertical = false},
{name = 'TurretArms', rotationSpeed = .1, angleConstraint = 1.1, vertical = true}
},
fireFx = {
{
+47 -45
View File
@@ -20,13 +20,12 @@ namespace battleship{
Weapon::Weapon(Unit *u, sol::table unitTable, int wid) :
unit(u),
id(wid),
maxAngle(PI / 2 * .7),
rateOfFire(unitTable["weapons"][wid + 1]["rateOfFire"]),
damage(unitTable["weapons"][wid + 1]["damage"].get_or(0))
{
sol::table weaponTable = unitTable["weapons"][wid + 1];
maxRange = weaponTable["maxRange"];
maxFireAngle = weaponTable["maxFireAngle"].get_or(.4);
maxFireAngle = weaponTable["maxFireAngle"].get_or(.1);
orderType = (Order::TYPE)weaponTable["orderType"];
initProjectileData(weaponTable);
@@ -52,10 +51,20 @@ namespace battleship{
for(int i = 0; i < numNodes; i++){
sol::table nodeTbl = weaponTable["nodes"][i + 1];
rotSpeed = nodeTbl["rotationSpeed"];
float rotSpeed = nodeTbl["rotationSpeed"];
bool vertical = nodeTbl["vertical"];
sol::optional<float> angleConstrOpt = nodeTbl["angleConstraint"];
float angleConstr;
if(angleConstrOpt != sol::nullopt)
angleConstr = nodeTbl["angleConstraint"];
else angleConstr = (vertical ? PI / 2 : 0);
string name = nodeTbl["name"];
nodes.push_back(unit->getModel()->findDescendant(name, true));
Node *node = unit->getModel()->findDescendant(name, true);
components.push_back(Component(node, rotSpeed, angleConstr, vertical));
}
}
@@ -114,14 +123,10 @@ namespace battleship{
if(ordTp == (int)orderType){
Vector3 targPos = (targDestruct ? targDestruct->getPos() : unit->getOrder(0).targets[0].pos);
float targDist = unit->getPos().getDistanceFrom(targPos);
bool withinRange = (minRange <= targDist && targDist <= maxRange);
bool withinAngle = true;
if(!nodes.empty()){
Vector3 dirVec = nodes[nodes.size() - 1]->getGlobalAxis(2);
withinAngle = Vector3(dirVec.x, 0, dirVec.z).norm().getAngleBetween((targPos - unit->getPos()).norm()) <= maxFireAngle;
}
Vector3 dirVec = (components.empty() ? unit->getDirVec() : components[components.size() - 1].node->getGlobalAxis(2));
bool withinAngle = (dirVec.getAngleBetween((targPos - unit->getPos()).norm()) <= maxFireAngle);
if((Order::TYPE)ordTp == Order::TYPE::ATTACK && withinRange && withinAngle)
fire(unit->getOrder(0));
@@ -211,42 +216,39 @@ namespace battleship{
lastFireTime = getTime();
}
void Weapon::alignNode(Node *node, Vector3 targPos, bool vertical){
Vector3 unitPos = unit->getPos();
Vector3 unitUp = unit->getUpVec();
Vector3 targDir = (targPos - unitPos).norm();
Vector3 compVec, rotAxis;
float rotAngle;
if(vertical){
compVec = getVecToPlane(unitPos, targDir, unitUp);
float angle1 = targDir.getAngleBetween(compVec);
float angle2 = node->getGlobalAxis(2).getAngleBetween(getVecToPlane(unitPos, node->getGlobalAxis(2), unitUp));
float angleDiff = angle1 - angle2;
rotAngle = (rotSpeed < fabs(angleDiff) ? rotSpeed : fabs(angleDiff)) * (angleDiff > 0 ? -1 : 1);
if(angle2 - rotAngle > maxAngle)
rotAngle = -(fabs(rotAngle) - (angle2 + fabs(rotAngle) - maxAngle));
rotAxis = Vector3::VEC_I;
}
else{
targDir = getVecToPlane(unitPos, targDir, unitUp);
compVec = node->getGlobalAxis(2);
bool negate = (node->getGlobalAxis(0).getAngleBetween(targDir) < PI / 2);
float angle = compVec.getAngleBetween(targDir);
rotAngle = (negate ? 1 : -1) * (rotSpeed < angle ? rotSpeed : angle);
rotAxis = Vector3::VEC_J;
}
Quaternion rot = Quaternion(rotAngle, rotAxis) * node->getOrientation();
node->setOrientation(rot);
}
//TODO improve to allow for vertical alignment
void Weapon::trackTarget(Vector3 targPos){
if(nodes.size() >= 1) alignNode(nodes[0], targPos, false);
if(nodes.size() >= 2) alignNode(nodes[1], targPos, true);
for(Component &component : components){
Vector3 unitPos = unit->getPos();
Vector3 unitUp = unit->getUpVec();
Vector3 targDir = (targPos - unitPos).norm();
Vector3 targDirProj = getVecToPlane(unitPos, targDir, unitUp);
Vector3 nodeDir = component.node->getGlobalAxis(2);
Vector3 rotAxis;
float rotAngle;
if(component.vertical){
float angle1 = targDir.getAngleBetween(targDirProj);
float angle2 = nodeDir.getAngleBetween(getVecToPlane(unitPos, nodeDir, unitUp));
float angleDiff = angle1 - angle2;
rotAngle = (component.rotSpeed < fabs(angleDiff) ? component.rotSpeed : fabs(angleDiff)) * (angleDiff > 0 ? -1 : 1);
if(angle2 - rotAngle > component.angleConstr)
rotAngle = -(fabs(rotAngle) - (angle2 + fabs(rotAngle) - component.angleConstr));
rotAxis = Vector3::VEC_I;
}
else{
bool negate = (component.node->getGlobalAxis(0).getAngleBetween(targDirProj) < PI / 2);
float angle = nodeDir.getAngleBetween(targDirProj);
rotAngle = (negate ? 1 : -1) * (component.rotSpeed < angle ? component.rotSpeed : angle);
rotAxis = Vector3::VEC_J;
}
Quaternion rot = Quaternion(rotAngle, rotAxis) * component.node->getOrientation();
component.node->setOrientation(rot);
}
}
}
+14 -3
View File
@@ -21,6 +21,18 @@ namespace battleship{
public:
enum class Type{FREEZER = 1};
struct Component{
vb01::Node *node = nullptr;
float rotSpeed, angleConstr;
bool vertical;
Component(vb01::Node *n, float rs, float ac, bool v) :
node(n),
rotSpeed(rs),
angleConstr(ac),
vertical(v) {}
};
Weapon(Unit*, sol::table, int);
~Weapon();
virtual void update();
@@ -37,22 +49,21 @@ namespace battleship{
Unit *unit = nullptr;
Order::TYPE orderType;
int id, projId = -1, damage = 0;
float minRange = 0, maxRange, rotSpeed, maxFireAngle, horConstraint = 1.57, vertConstraint = 1.57, maxAngle;
float minRange = 0, maxRange, maxFireAngle;
vb01::s64 lastFireTime = 0;
FxManager::Fx *fireFx = nullptr;
vb01::Quaternion projRot;
vb01::Vector3 projPos;
std::vector<vb01::Node*> nodes;
vb01::Node *projPar = nullptr;
static std::string LASER_FLAG;
void initProjectileData(sol::table);
void initNodes(sol::table);
void useFx(FxManager::Fx*, vb01::Vector3, bool);
void alignNode(vb01::Node*, vb01::Vector3, bool);
inline bool canFire(){return vb01::getTime() - lastFireTime > rateOfFire;}
protected:
int rateOfFire;
std::vector<Component> components;
virtual void updateTarget(GameObject*);
};