431a9c00a5
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably. 99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified. Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects. Most remaining warnings are now unused parameters.
312 lines
11 KiB
C++
312 lines
11 KiB
C++
#include "StarDamage.hpp"
|
|
#include "StarJsonExtra.hpp"
|
|
#include "StarDataStreamExtra.hpp"
|
|
#include "StarRoot.hpp"
|
|
|
|
namespace Star {
|
|
|
|
DamageSource::DamageSource()
|
|
: damageType(DamageType::NoDamage), damage(0.0), sourceEntityId(NullEntityId), rayCheck(false) {}
|
|
|
|
DamageSource::DamageSource(Json const& config) {
|
|
if (auto dtype = config.optString("damageType"))
|
|
damageType = DamageTypeNames.getLeft(*dtype);
|
|
else
|
|
damageType = DamageType::Damage;
|
|
|
|
if (config.contains("poly"))
|
|
damageArea = jsonToPolyF(config.get("poly"));
|
|
else if (config.contains("line"))
|
|
damageArea = jsonToLine2F(config.get("line"));
|
|
else
|
|
throw StarException("No 'poly' or 'line' key in DamageSource config");
|
|
|
|
damage = config.getFloat("damage");
|
|
|
|
trackSourceEntity = config.getBool("trackSourceEntity", true);
|
|
sourceEntityId = config.getInt("sourceEntityId", NullEntityId);
|
|
|
|
if (auto tconfig = config.opt("team")) {
|
|
team = EntityDamageTeam(*tconfig);
|
|
} else {
|
|
team.type = TeamTypeNames.getLeft(config.getString("teamType", "passive"));
|
|
team.team = config.getUInt("teamNumber", 0);
|
|
}
|
|
|
|
damageRepeatGroup = config.optString("damageRepeatGroup");
|
|
damageRepeatTimeout = config.optFloat("damageRepeatTimeout");
|
|
|
|
damageSourceKind = config.getString("damageSourceKind", "");
|
|
|
|
statusEffects = config.getArray("statusEffects", {}).transformed(jsonToEphemeralStatusEffect);
|
|
|
|
auto knockbackJson = config.get("knockback", Json(0.0f));
|
|
if (knockbackJson.isType(Json::Type::Array))
|
|
knockback = jsonToVec2F(knockbackJson);
|
|
else
|
|
knockback = knockbackJson.toFloat();
|
|
|
|
rayCheck = config.getBool("rayCheck", false);
|
|
}
|
|
|
|
DamageSource::DamageSource(DamageType damageType,
|
|
DamageArea damageArea,
|
|
float damage,
|
|
bool trackSourceEntity,
|
|
EntityId sourceEntityId,
|
|
EntityDamageTeam team,
|
|
Maybe<String> damageRepeatGroup,
|
|
Maybe<float> damageRepeatTimeout,
|
|
String damageSourceKind,
|
|
List<EphemeralStatusEffect> statusEffects,
|
|
Knockback knockback,
|
|
bool rayCheck)
|
|
: damageType(std::move(damageType)),
|
|
damageArea(std::move(damageArea)),
|
|
damage(std::move(damage)),
|
|
trackSourceEntity(std::move(trackSourceEntity)),
|
|
sourceEntityId(std::move(sourceEntityId)),
|
|
team(std::move(team)),
|
|
damageRepeatGroup(std::move(damageRepeatGroup)),
|
|
damageRepeatTimeout(std::move(damageRepeatTimeout)),
|
|
damageSourceKind(std::move(damageSourceKind)),
|
|
statusEffects(std::move(statusEffects)),
|
|
knockback(std::move(knockback)),
|
|
rayCheck(std::move(rayCheck)) {}
|
|
|
|
Json DamageSource::toJson() const {
|
|
Json damageAreaJson;
|
|
if (auto p = damageArea.ptr<PolyF>())
|
|
damageAreaJson = jsonFromPolyF(*p);
|
|
else if (auto l = damageArea.ptr<Line2F>())
|
|
damageAreaJson = jsonFromLine2F(*l);
|
|
|
|
Json knockbackJson;
|
|
if (auto p = knockback.ptr<float>())
|
|
knockbackJson = *p;
|
|
else if (auto p = knockback.ptr<Vec2F>())
|
|
knockbackJson = jsonFromVec2F(*p);
|
|
|
|
return JsonObject{{"damageType", DamageTypeNames.getRight(damageType)},
|
|
{"damageArea", damageAreaJson},
|
|
{"damage", damage},
|
|
{"trackSourceEntity", trackSourceEntity},
|
|
{"sourceEntityId", sourceEntityId},
|
|
{"team", team.toJson()},
|
|
{"damageRepeatGroup", jsonFromMaybe(damageRepeatGroup)},
|
|
{"damageRepeatTimeout", jsonFromMaybe(damageRepeatTimeout)},
|
|
{"damageSourceKind", damageSourceKind},
|
|
{"statusEffects", statusEffects.transformed(jsonFromEphemeralStatusEffect)},
|
|
{"knockback", knockbackJson},
|
|
{"rayCheck", rayCheck}};
|
|
}
|
|
|
|
bool DamageSource::intersectsWithPoly(WorldGeometry const& geometry, PolyF const& targetPoly) const {
|
|
if (auto poly = damageArea.ptr<PolyF>())
|
|
return geometry.polyIntersectsPoly(*poly, targetPoly);
|
|
else if (auto line = damageArea.ptr<Line2F>())
|
|
return geometry.lineIntersectsPoly(*line, targetPoly);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
Vec2F DamageSource::knockbackMomentum(WorldGeometry const& worldGeometry, Vec2F const& targetCenter) const {
|
|
if (auto v = knockback.ptr<Vec2F>()) {
|
|
return *v;
|
|
} else if (auto s = knockback.ptr<float>()) {
|
|
if (*s != 0) {
|
|
if (auto poly = damageArea.ptr<PolyF>())
|
|
return worldGeometry.diff(targetCenter, poly->center()).normalized() * *s;
|
|
else if (auto line = damageArea.ptr<Line2F>())
|
|
return vnorm(line->diff()) * *s;
|
|
}
|
|
}
|
|
|
|
return Vec2F();
|
|
}
|
|
|
|
bool DamageSource::operator==(DamageSource const& rhs) const {
|
|
return tie(damageType, damageArea, damage, trackSourceEntity, sourceEntityId, team, damageSourceKind, statusEffects, knockback, rayCheck)
|
|
== tie(rhs.damageType,
|
|
rhs.damageArea,
|
|
rhs.damage,
|
|
rhs.trackSourceEntity,
|
|
rhs.sourceEntityId,
|
|
rhs.team,
|
|
rhs.damageSourceKind,
|
|
rhs.statusEffects,
|
|
rhs.knockback,
|
|
rhs.rayCheck);
|
|
}
|
|
|
|
DamageSource& DamageSource::translate(Vec2F const& position) {
|
|
if (auto poly = damageArea.ptr<PolyF>())
|
|
poly->translate(position);
|
|
else if (auto line = damageArea.ptr<Line2F>())
|
|
line->translate(position);
|
|
return *this;
|
|
}
|
|
|
|
DataStream& operator<<(DataStream& ds, DamageSource const& damageSource) {
|
|
ds.write(damageSource.damageType);
|
|
ds.write(damageSource.damageArea);
|
|
ds.write(damageSource.damage);
|
|
ds.write(damageSource.trackSourceEntity);
|
|
ds.write(damageSource.sourceEntityId);
|
|
ds.write(damageSource.team);
|
|
ds.write(damageSource.damageRepeatGroup);
|
|
ds.write(damageSource.damageRepeatTimeout);
|
|
ds.write(damageSource.damageSourceKind);
|
|
ds.write(damageSource.statusEffects);
|
|
ds.write(damageSource.knockback);
|
|
ds.write(damageSource.rayCheck);
|
|
return ds;
|
|
}
|
|
|
|
DataStream& operator>>(DataStream& ds, DamageSource& damageSource) {
|
|
ds.read(damageSource.damageType);
|
|
ds.read(damageSource.damageArea);
|
|
ds.read(damageSource.damage);
|
|
ds.read(damageSource.trackSourceEntity);
|
|
ds.read(damageSource.sourceEntityId);
|
|
ds.read(damageSource.team);
|
|
ds.read(damageSource.damageRepeatGroup);
|
|
ds.read(damageSource.damageRepeatTimeout);
|
|
ds.read(damageSource.damageSourceKind);
|
|
ds.read(damageSource.statusEffects);
|
|
ds.read(damageSource.knockback);
|
|
ds.read(damageSource.rayCheck);
|
|
return ds;
|
|
}
|
|
|
|
DamageRequest::DamageRequest()
|
|
: hitType(HitType::Hit), damageType(DamageType::Damage), damage(0.0f), sourceEntityId(NullEntityId) {}
|
|
|
|
DamageRequest::DamageRequest(Json const& v) {
|
|
hitType = HitTypeNames.getLeft(v.getString("hitType", "hit"));
|
|
damageType = DamageTypeNames.getLeft(v.getString("damageType", "damage"));
|
|
damage = v.getFloat("damage");
|
|
knockbackMomentum = jsonToVec2F(v.get("knockbackMomentum", JsonArray{0, 0}));
|
|
sourceEntityId = v.getInt("sourceEntityId", NullEntityId);
|
|
damageSourceKind = v.getString("damageSourceKind", "");
|
|
statusEffects = v.getArray("statusEffects", {}).transformed(jsonToEphemeralStatusEffect);
|
|
}
|
|
|
|
DamageRequest::DamageRequest(HitType hitType,
|
|
DamageType damageType,
|
|
float damage,
|
|
Vec2F const& knockbackMomentum,
|
|
EntityId sourceEntityId,
|
|
String const& damageSourceKind,
|
|
List<EphemeralStatusEffect> const& statusEffects)
|
|
: hitType(hitType),
|
|
damageType(damageType),
|
|
damage(damage),
|
|
knockbackMomentum(knockbackMomentum),
|
|
sourceEntityId(sourceEntityId),
|
|
damageSourceKind(damageSourceKind),
|
|
statusEffects(statusEffects) {}
|
|
|
|
Json DamageRequest::toJson() const {
|
|
return JsonObject{{"hitType", HitTypeNames.getRight(hitType)},
|
|
{"damageType", DamageTypeNames.getRight(damageType)},
|
|
{"damage", damage},
|
|
{"knockbackMomentum", jsonFromVec2F(knockbackMomentum)},
|
|
{"sourceEntityId", sourceEntityId},
|
|
{"damageSourceKind", damageSourceKind},
|
|
{"statusEffects", statusEffects.transformed(jsonFromEphemeralStatusEffect)}};
|
|
}
|
|
|
|
DataStream& operator<<(DataStream& ds, DamageRequest const& damageRequest) {
|
|
ds << damageRequest.hitType;
|
|
ds << damageRequest.damageType;
|
|
ds << damageRequest.damage;
|
|
ds << damageRequest.knockbackMomentum;
|
|
ds << damageRequest.sourceEntityId;
|
|
ds << damageRequest.damageSourceKind;
|
|
ds << damageRequest.statusEffects;
|
|
return ds;
|
|
}
|
|
|
|
DataStream& operator>>(DataStream& ds, DamageRequest& damageRequest) {
|
|
ds >> damageRequest.hitType;
|
|
ds >> damageRequest.damageType;
|
|
ds >> damageRequest.damage;
|
|
ds >> damageRequest.knockbackMomentum;
|
|
ds >> damageRequest.sourceEntityId;
|
|
ds >> damageRequest.damageSourceKind;
|
|
ds >> damageRequest.statusEffects;
|
|
return ds;
|
|
}
|
|
|
|
DamageNotification::DamageNotification() : sourceEntityId(), targetEntityId(), damageDealt(), healthLost() {}
|
|
|
|
DamageNotification::DamageNotification(Json const& v) {
|
|
sourceEntityId = v.getInt("sourceEntityId");
|
|
targetEntityId = v.getInt("targetEntityId");
|
|
position = jsonToVec2F(v.get("position"));
|
|
damageDealt = v.getFloat("damageDealt");
|
|
healthLost = v.getFloat("healthLost");
|
|
hitType = HitTypeNames.getLeft(v.getString("hitType"));
|
|
damageSourceKind = v.getString("damageSourceKind");
|
|
targetMaterialKind = v.getString("targetMaterialKind");
|
|
}
|
|
|
|
DamageNotification::DamageNotification(EntityId sourceEntityId,
|
|
EntityId targetEntityId,
|
|
Vec2F position,
|
|
float damageDealt,
|
|
float healthLost,
|
|
HitType hitType,
|
|
String damageSourceKind,
|
|
String targetMaterialKind)
|
|
: sourceEntityId(sourceEntityId),
|
|
targetEntityId(targetEntityId),
|
|
position(position),
|
|
damageDealt(damageDealt),
|
|
healthLost(healthLost),
|
|
hitType(hitType),
|
|
damageSourceKind(std::move(damageSourceKind)),
|
|
targetMaterialKind(std::move(targetMaterialKind)) {}
|
|
|
|
Json DamageNotification::toJson() const {
|
|
return JsonObject{{"sourceEntityId", sourceEntityId},
|
|
{"targetEntityId", targetEntityId},
|
|
{"position", jsonFromVec2F(position)},
|
|
{"damageDealt", damageDealt},
|
|
{"healthLost", healthLost},
|
|
{"hitType", HitTypeNames.getRight(hitType)},
|
|
{"damageSourceKind", damageSourceKind},
|
|
{"targetMaterialKind", targetMaterialKind}};
|
|
}
|
|
|
|
DataStream& operator<<(DataStream& ds, DamageNotification const& damageNotification) {
|
|
ds.viwrite(damageNotification.sourceEntityId);
|
|
ds.viwrite(damageNotification.targetEntityId);
|
|
ds.vfwrite(damageNotification.position[0], 0.01f);
|
|
ds.vfwrite(damageNotification.position[1], 0.01f);
|
|
ds.write(damageNotification.damageDealt);
|
|
ds.write(damageNotification.healthLost);
|
|
ds.write(damageNotification.hitType);
|
|
ds.write(damageNotification.damageSourceKind);
|
|
ds.write(damageNotification.targetMaterialKind);
|
|
|
|
return ds;
|
|
}
|
|
|
|
DataStream& operator>>(DataStream& ds, DamageNotification& damageNotification) {
|
|
ds.viread(damageNotification.sourceEntityId);
|
|
ds.viread(damageNotification.targetEntityId);
|
|
ds.vfread(damageNotification.position[0], 0.01f);
|
|
ds.vfread(damageNotification.position[1], 0.01f);
|
|
ds.read(damageNotification.damageDealt);
|
|
ds.read(damageNotification.healthLost);
|
|
ds.read(damageNotification.hitType);
|
|
ds.read(damageNotification.damageSourceKind);
|
|
ds.read(damageNotification.targetMaterialKind);
|
|
|
|
return ds;
|
|
}
|
|
|
|
}
|