/* =========================================================================== Copyright (C) 2023 the OpenMoHAA team This file is part of OpenMoHAA source code. OpenMoHAA source code 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 2 of the License, or (at your option) any later version. OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // DESCRIPTION: // General swiping functions #include "cg_commands.h" swipething_t m_swipes[MAX_SWIPES]; extern int current_entity_number; extern refEntity_t *current_entity; extern dtiki_t *current_tiki; extern centity_t *current_centity; void ClientGameCommandManager::SwipeOn(Event *ev) { // Make a swipe for this if available int i; int freeswipe = -1; str tagname_start, tagname_end; qhandle_t shader; if (ev->NumArgs() != 4) { return; } shader = cgi.R_RegisterShader(ev->GetString(1)); tagname_start = ev->GetString(2); tagname_end = ev->GetString(3); for (i = 0; i < MAX_SWIPES; i++) { swipething_t& swipe = m_swipes[i]; if (!swipe.enabled || ((swipe.entitynum == current_entity_number) && (tagname_start == swipe.tagname_start) && (tagname_end == swipe.tagname_end) && (shader == swipe.shader))) { freeswipe = i; break; } } if (freeswipe == -1) { return; } swipething_t& swipe = m_swipes[freeswipe]; if (!swipe.enabled) { swipe.Init(); swipe.enabled = qtrue; swipe.entitynum = current_entity_number; } swipe.shader = cgi.R_RegisterShader(ev->GetString(1)); swipe.tagname_start = ev->GetString(2); swipe.tagname_end = ev->GetString(3); swipe.life = ev->GetFloat(4) * 1000.f; if (current_centity) { current_centity->clientFlags |= CF_UPDATESWIPE; } } void ClientGameCommandManager::SwipeOff(Event *ev) { qboolean was_enabled; int i; was_enabled = qfalse; for (i = 0; i < MAX_SWIPES; i++) { swipething_t& swipe = m_swipes[i]; if (swipe.enabled && swipe.entitynum == current_entity_number) { swipe.enabled = qfalse; was_enabled = qtrue; } } if (was_enabled) { //cgi.R_SwipeBegin ( 0.f, 0.f, -1 ); //cgi.R_SwipeEnd (); if (current_centity) { current_centity->clientFlags &= ~CF_UPDATESWIPE; } } } void ClientGameCommandManager::Swipe(Event *ev) { // This does a swipe effect on the entity int i, swipenum; orientation_t _or; int tagnum_start, tagnum_end; qboolean add_cnt_point = qfalse; vec3_t tmp; assert(current_entity); assert(current_tiki); if (!current_entity || !current_tiki) { return; } // Let's find us a new (or current) swipe for (swipenum = 0; swipenum < MAX_SWIPES; swipenum++) { swipething_t& swipe = m_swipes[swipenum]; if (swipe.enabled && swipe.entitynum == current_entity_number) { while (swipe.num_live_swipes > 1) { i = (swipe.first_swipe + 1) % MAX_SWIPE_POINTS; swipepoint_t& swipepoint = swipe.swipepoints[i]; if (swipepoint.time < cg.time - swipe.life) { // then let's delete the previous swipe.first_swipe = (swipe.first_swipe + 1) % MAX_SWIPE_POINTS; swipe.num_live_swipes--; } else { break; } } if (swipe.num_live_swipes == 1) { swipepoint_t& swipepoint = swipe.swipepoints[swipe.first_swipe]; if (swipepoint.time < cg.time - swipe.life) { swipe.num_live_swipes = 0; } } swipe.cntPoint.time = cg.time; VectorCopy(current_entity->origin, swipe.cntPoint.points[0]); tagnum_start = cgi.Tag_NumForName(current_tiki, swipe.tagname_start.c_str()); _or = cgi.TIKI_Orientation(current_entity, tagnum_start); // Clear out the points VectorClear(tmp); VectorClear(swipe.cntPoint.points[0]); VectorClear(swipe.cntPoint.points[1]); if (ev->NumArgs() > 0) { VectorCopy(ev->GetVector(1), tmp); } else { VectorCopy(current_entity->origin, tmp); } // Transform the origin of the tag by the axis of the entity and add it to the origin of the entity for (i = 0; i < 3; i++) { VectorMA(tmp, _or.origin[i], current_entity->axis[i], tmp); } // Copy tmp into the startpoint VectorCopy(tmp, swipe.cntPoint.points[0]); tagnum_end = cgi.Tag_NumForName(current_tiki, swipe.tagname_end.c_str()); _or = cgi.TIKI_Orientation(current_entity, tagnum_end); if (ev->NumArgs() > 0) { VectorCopy(ev->GetVector(1), tmp); } else { VectorCopy(current_entity->origin, tmp); } // Transform the origin of the tag by the axis of the entity and add it to the origin of the entity for (i = 0; i < 3; i++) { VectorMA(tmp, _or.origin[i], current_entity->axis[i], tmp); } // Copy tmp into the startpoint VectorCopy(tmp, swipe.cntPoint.points[1]); if (swipe.num_live_swipes == 0) { add_cnt_point = qtrue; } else { float deltime = swipe.life / float(MAX_SWIPES); swipepoint_t& lastpoint = swipe.swipepoints[(swipe.first_swipe + swipe.num_live_swipes - 1) % MAX_SWIPE_POINTS]; if (swipe.cntPoint.time - lastpoint.time >= deltime) { add_cnt_point = qtrue; } } cgi.R_SwipeBegin(cg.time, swipe.life, swipe.shader); if (add_cnt_point) { swipepoint_t& swipepoint = swipe.swipepoints[(swipe.first_swipe + swipe.num_live_swipes) % MAX_SWIPE_POINTS]; swipepoint = swipe.cntPoint; if (swipe.num_live_swipes == MAX_SWIPE_POINTS) { swipe.first_swipe = (swipe.first_swipe + 1) % MAX_SWIPE_POINTS; } else { swipe.num_live_swipes++; } } for (i = 0; i != swipe.num_live_swipes; i++) { swipepoint_t& swipepoint = swipe.swipepoints[(swipe.first_swipe + i) % MAX_SWIPE_POINTS]; cgi.R_SwipePoint(swipepoint.points[0], swipepoint.points[1], swipepoint.time); } if (!add_cnt_point) { cgi.R_SwipePoint(swipe.cntPoint.points[0], swipe.cntPoint.points[1], swipe.cntPoint.time); } cgi.R_SwipeEnd(); } } } void ClientGameCommandManager::ClearSwipes(void) { int i; for (i = 0; i < MAX_SWIPES; i++) { swipething_t& swipe = m_swipes[i]; swipe.enabled = qfalse; } cgi.R_SwipeBegin(0.f, 0.f, -1); cgi.R_SwipeEnd(); } /* =================== CG_ClearSwipes This is called at startup and for tournement restarts =================== */ void CG_ClearSwipes(void) { commandManager.ClearSwipes(); }