Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions code/model/animation/modelanimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,12 +1062,31 @@ namespace animation {
return true;
}

bool ModelAnimationSet::advanceMoveableToFinal(polymodel_instance* pmi, const SCP_string& name) const {
SCP_string lowername = name;
SCP_tolower(lowername);
auto moveable = m_moveableSet.find(lowername);
if (moveable == m_moveableSet.end())
return false;

moveable->second->advanceToFinalState(pmi);
return true;
}

void ModelAnimationSet::initializeMoveables(polymodel_instance* pmi) {
for(const auto& moveable : m_moveableSet){
moveable.second->initialize(this, pmi);
}
}

void ModelAnimationMoveable::advanceToFinalState(polymodel_instance* pmi) {
auto it = m_instances.find(pmi->id);
if (it == m_instances.end() || !it->second.animation)
return;

it->second.animation->start(pmi, ModelAnimationDirection::FWD, true, true);
}

SCP_vector<SCP_string> ModelAnimationSet::getRegisteredMoveables() const {
SCP_vector<SCP_string> ret;

Expand Down
3 changes: 3 additions & 0 deletions code/model/animation/modelanimation.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ namespace animation {

virtual void update(polymodel_instance* pmi, const SCP_vector<std::any>& args) = 0;
virtual void initialize(ModelAnimationSet* parentSet, polymodel_instance* pmi) = 0;

void advanceToFinalState(polymodel_instance* pmi);
};


Expand Down Expand Up @@ -368,6 +370,7 @@ namespace animation {
SCP_set<SCP_string> getRegisteredAnimNames() const;

bool updateMoveable(polymodel_instance* pmi, const SCP_string& name, const SCP_vector<std::any>& args) const;
bool advanceMoveableToFinal(polymodel_instance* pmi, const SCP_string& name) const;
void initializeMoveables(polymodel_instance* pmi);
SCP_vector<SCP_string> getRegisteredMoveables() const;

Expand Down
2 changes: 1 addition & 1 deletion code/model/animation/modelanimation_segments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,7 @@ namespace animation {
ik->addNode(submodel, chainlink.constraint.get());
}

ik->solve(m_targetPosition, &(*m_targetRotation));
ik->solve(m_targetPosition, m_targetRotation ? &*m_targetRotation : nullptr);

auto chainlink_it = m_chain.cbegin();
for(const auto& solvedlink : *ik){
Expand Down
38 changes: 37 additions & 1 deletion code/parse/sexp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ SCP_vector<sexp_oper> Operators = {
{ "trigger-ship-animation", OP_TRIGGER_ANIMATION_NEW, 3, 7, SEXP_ACTION_OPERATOR, }, //Lafiel
{ "stop-looping-animation", OP_STOP_LOOPING_ANIMATION, 3, 3, SEXP_ACTION_OPERATOR, }, //Lafiel
{ "update-moveable-animation", OP_UPDATE_MOVEABLE, 2, INT_MAX, SEXP_ACTION_OPERATOR, }, //Lafiel
{ "advance-moveable-animation", OP_ADVANCE_MOVEABLE, 2, 2, SEXP_ACTION_OPERATOR, }, //Lafiel

//Coordinate Manipulation Sub-Category
{ "set-object-position", OP_SET_OBJECT_POSITION, 4, 4, SEXP_ACTION_OPERATOR, }, // WMC
Expand Down Expand Up @@ -2870,7 +2871,8 @@ int check_sexp_syntax(int node, int desired_return_type, int recursive, int *bad

break;
}
case OP_UPDATE_MOVEABLE: {
case OP_UPDATE_MOVEABLE:
case OP_ADVANCE_MOVEABLE:{
//Second OP name
SCP_string name = CTEXT(CDR(ship_node));
SCP_tolower(name);
Expand Down Expand Up @@ -23557,6 +23559,19 @@ void sexp_update_moveable_animation(int node)
Ship_info[ship_entry->shipp()->ship_info_index].animations.updateMoveable(model_get_instance(ship_entry->shipp()->model_instance_num), name, args);
}

void sexp_advance_moveable_animation(int node)
{
auto ship_entry = eval_ship(node);
if (!ship_entry || !ship_entry->has_shipp())
return;

node = CDR(node);

SCP_string name(CTEXT(node));

Ship_info[ship_entry->shipp()->ship_info_index].animations.advanceMoveableToFinal(model_get_instance(ship_entry->shipp()->model_instance_num), name);
}

void sexp_add_remove_escort(int node)
{
int flag;
Expand Down Expand Up @@ -30675,6 +30690,11 @@ int eval_sexp(int cur_node, int referenced_node)
sexp_update_moveable_animation(node);
break;

case OP_ADVANCE_MOVEABLE:
sexp_val = SEXP_TRUE;
sexp_advance_moveable_animation(node);
break;

case OP_STOP_LOOPING_ANIMATION:
sexp_val = SEXP_TRUE;
sexp_stop_looping_animation(node);
Expand Down Expand Up @@ -32013,6 +32033,7 @@ int query_operator_return_type(int op)
case OP_SET_ALPHA_MULT:
case OP_TRIGGER_ANIMATION_NEW:
case OP_UPDATE_MOVEABLE:
case OP_ADVANCE_MOVEABLE:
case OP_STOP_LOOPING_ANIMATION:
case OP_CONTAINER_ADD_TO_LIST:
case OP_CONTAINER_REMOVE_FROM_LIST:
Expand Down Expand Up @@ -34939,6 +34960,12 @@ int query_operator_argument_type(int op_index, int argnum)
else
return OPF_NUMBER;

case OP_ADVANCE_MOVEABLE:
if (argnum == 0)
return OPF_SHIP;
else
return OPF_ANIMATION_NAME;

case OP_IS_CONTAINER_EMPTY:
case OP_GET_CONTAINER_SIZE:
if (argnum == 0) {
Expand Down Expand Up @@ -37210,6 +37237,7 @@ int get_category(int op_id)
case OP_DESTROY_INSTANTLY_WITH_DEBRIS:
case OP_TRIGGER_ANIMATION_NEW:
case OP_UPDATE_MOVEABLE:
case OP_ADVANCE_MOVEABLE:
case OP_NAV_SET_COLOR:
case OP_NAV_SET_VISITED_COLOR:
case OP_CONTAINER_ADD_TO_LIST:
Expand Down Expand Up @@ -37547,6 +37575,7 @@ int get_subcategory(int op_id)
case OP_SET_ALPHA_MULT:
case OP_TRIGGER_ANIMATION_NEW:
case OP_UPDATE_MOVEABLE:
case OP_ADVANCE_MOVEABLE:
case OP_STOP_LOOPING_ANIMATION:
return CHANGE_SUBCATEGORY_MODELS_AND_TEXTURES;

Expand Down Expand Up @@ -42871,6 +42900,13 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"\tThree optional numbers: x, y, z rotation target relative to base, in degrees\r\n"
},

{ OP_ADVANCE_MOVEABLE, "advance-moveable-animation\r\n"
"\tAdvances a moveable animation to its final state instantly.\r\n"
"Takes 2 arguments...\r\n"
"\t1: The ship (ship must be in-mission).\r\n"
"\t2: The name of the moveable.\r\n"
},

{ OP_TOGGLE_ASTEROID_FIELD, "toggle-asteroid-field\r\n"
"\tTurns an existing asteroid or debris field on/off. Will do nothing if no field is defined in the mission file or set with sexps.\r\n"
"\tNote that this differs from actually removing and adding a field in that it only toggles a field from being rendered or calculated.\r\n"
Expand Down
1 change: 1 addition & 0 deletions code/parse/sexp.h
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,7 @@ enum : int {
OP_DESTROY_INSTANTLY_WITH_DEBRIS, // Asteroth
OP_TRIGGER_ANIMATION_NEW, // Lafiel
OP_UPDATE_MOVEABLE, // Lafiel
OP_ADVANCE_MOVEABLE, // Lafiel
OP_NAV_SET_COLOR, // Goober5000
OP_NAV_SET_VISITED_COLOR, // Goober5000
OP_CONTAINER_ADD_TO_LIST, // Karajorma/jg18
Expand Down
17 changes: 17 additions & 0 deletions code/scripting/api/objs/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2311,6 +2311,23 @@ ADE_FUNC(updateSubmodelMoveable, l_Ship, "string name, table values",
return Ship_info[shipp->ship_info_index].animations.updateMoveable(model_get_instance(shipp->model_instance_num), name, valuesMoveable) ? ADE_RETURN_TRUE : ADE_RETURN_FALSE;
}

ADE_FUNC(advanceSubmodelMoveableToFinal, l_Ship, "string name",
"Advances a moveable animation to its final state immediately. Name is the name of the moveable.",
"boolean", "True if successful, false or nil otherwise")
{
object_h* objh;
const char* name = nullptr;

if (!ade_get_args(L, "os", l_Ship.GetPtr(&objh), &name))
return ADE_RETURN_NIL;

if (!objh->isValid())
return ADE_RETURN_NIL;

ship* shipp = &Ships[objh->objp()->instance];
return Ship_info[shipp->ship_info_index].animations.advanceMoveableToFinal(model_get_instance(shipp->model_instance_num), name) ? ADE_RETURN_TRUE : ADE_RETURN_FALSE;
}

ADE_FUNC(warpIn, l_Ship, NULL, "Warps ship in", "boolean", "True if successful, or nil if ship handle is invalid")
{
object_h *objh;
Expand Down
Loading