6153 lines
217 KiB
Scheme
Executable File
6153 lines
217 KiB
Scheme
Executable File
//-------------------------------------------------
|
|
// File: ggsm_arcade_entity.sch
|
|
// Purpose: general functions required by system
|
|
//-------------------------------------------------
|
|
|
|
//-------------------------------------------------
|
|
// INCLUDES
|
|
//-------------------------------------------------
|
|
USING "ggsm_structs.sch"
|
|
USING "ggsm_maths.sch"
|
|
USING "ggsm_data.sch"
|
|
USING "ggsm_helpers.sch"
|
|
|
|
//-------------------------------------------------
|
|
// DEPTH SORTING FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
/// PURPOSE:
|
|
/// Reset Z Sort Array
|
|
/// PARAMS:
|
|
/// sArray -
|
|
PROC GGSM_RESET_ENTITY_DEPTHSORT_ARRAY()
|
|
INT i
|
|
|
|
REPEAT GGSM_MAX_ENTITIES i
|
|
sGGSMData.sZSortData[i].iEntityIndex = GGSM_INVALID_ENTITY
|
|
sGGSMData.sZSortData[i].iZDepth = -1
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sort Z Sort Array
|
|
/// PARAMS:
|
|
/// sArray - Array to sort
|
|
/// iLeft - left index
|
|
/// iRight - right index
|
|
PROC GGSM_QUICK_SORT_ZDEPTH_ARRAY(GGSM_ZSORTDATA &sArray[], INT iLeft, INT iRight)
|
|
|
|
INT i, j
|
|
INT p = sArray[((iLeft + iRight) / 2)].iZDepth
|
|
GGSM_ZSORTDATA q
|
|
i = iLeft
|
|
j = iRight
|
|
|
|
WHILE (i <= j)
|
|
|
|
WHILE ((sArray[i].iZDepth > p) AND (i < iRight))
|
|
i++
|
|
ENDWHILE
|
|
|
|
WHILE ((p > sArray[j].iZDepth) AND (j > iLeft))
|
|
j--
|
|
ENDWHILE
|
|
|
|
IF (i <= j)
|
|
q = sArray[i]
|
|
sArray[i] = sArray[j]
|
|
sArray[j] = q
|
|
|
|
i++
|
|
j--
|
|
ENDIF
|
|
|
|
ENDWHILE
|
|
|
|
IF (i < iRight)
|
|
GGSM_QUICK_SORT_ZDEPTH_ARRAY(sArray, i, iRight)
|
|
ENDIF
|
|
|
|
IF (iLeft < j)
|
|
GGSM_QUICK_SORT_ZDEPTH_ARRAY(sArray, iLeft, j)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
/// PURPOSE:
|
|
/// Sets Z Depth for zsorting
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// iZDepth -
|
|
PROC GGSM_ENTITY_SET_Z_DEPTH(GGSM_ENTITY &ent, INT iZDepth)
|
|
INT i
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_FORCE_Z_SORT)
|
|
REPEAT GGSM_MAX_ENTITIES i
|
|
IF (sGGSMData.sZSortData[i].iEntityIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent))
|
|
sGGSMData.sZSortData[i].iZDepth = iZDepth
|
|
EXIT
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
REPEAT GGSM_MAX_ENTITIES i
|
|
IF (sGGSMData.sZSortData[i].iEntityIndex = GGSM_INVALID_ENTITY)
|
|
sGGSMData.sZSortData[i].iZDepth = iZDepth
|
|
sGGSMData.sZSortData[i].iEntityIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
EXIT
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_CLEAR_Z_DEPTH(GGSM_ENTITY &ent)
|
|
INT i
|
|
|
|
REPEAT GGSM_MAX_ENTITIES i
|
|
IF (sGGSMData.sZSortData[i].iEntityIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent))
|
|
sGGSMData.sZSortData[i].iEntityIndex = GGSM_INVALID_ENTITY
|
|
sGGSMData.sZSortData[i].iZDepth = -1
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_FORCE_Z_SORT)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_PATH_INDEX(GGSM_ENTITY &ent, INT i)
|
|
ent.iPathNumber = i
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_RESET_BASE_SPEED(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
ent.fSpeed = dat.fBaseSpeed
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SCALE_BASE_SPEED(GGSM_ENTITY &ent, FLOAT fScale)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
ent.fSpeed = (dat.fBaseSpeed * fScale)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the speed multiplied by timescale
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// RETURNS:
|
|
///
|
|
FUNC FLOAT GGSM_ENTITY_GET_SPEED(GGSM_ENTITY &ent)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
RETURN ent.fSpeed
|
|
ENDIF
|
|
|
|
RETURN ent.fSpeed * sGGSMData.fTimeScale
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_SET_PACKED_ORIGIN(GGSM_ENTITY &ent, VECTOR_2D vec)
|
|
ent.iPackedLocalOrigin = GGSM_PACK_VECTOR_2D_TO_INT(vec)
|
|
ENDPROC
|
|
|
|
FUNC VECTOR_2D GGSM_GET_RANDOM_POINT_ON_ENTITY(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
VECTOR_2D size = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D pos = ent.sWorld.vPosition
|
|
size.x /= 2.0
|
|
size.y /= 2.0
|
|
pos.x += GET_RANDOM_FLOAT_IN_RANGE(-size.x, size.x)
|
|
pos.y += GET_RANDOM_FLOAT_IN_RANGE(-size.y, size.y)
|
|
RETURN pos
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_IS_MOVEMENT_COMPLETE(GGSM_ENTITY &ent)
|
|
IF (ent.eMoveType = GGSM_MOVEMENT_NONE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
ENDFUNC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY ARRAY FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
/// PURPOSE:
|
|
/// Counts # of entities free in array
|
|
/// PARAMS:
|
|
/// array -
|
|
/// RETURNS:
|
|
///
|
|
FUNC INT GGSM_COUNT_FREE_ENTITIES(GGSM_ENTITY &array[])
|
|
INT i
|
|
INT cnt = 0
|
|
REPEAT COUNT_OF(array) i
|
|
IF (array[i].eState = GGSM_ENTITY_STATE_NONE)
|
|
cnt ++
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN cnt
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the next free entity index
|
|
/// PARAMS:
|
|
/// array - entity array
|
|
/// ind - Index of the next free index
|
|
/// iSearchIndex - Index to start searching from
|
|
/// RETURNS:
|
|
/// TRUE if entity can be found
|
|
FUNC BOOL GGSM_GET_FREE_ENTITY(GGSM_ENTITY &array[], INT &ind, INT &iSearchIndex)
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
// stops any overflow nonsense
|
|
iSearchIndex = ABSI(iSearchIndex) % cnt
|
|
|
|
ind = GGSM_INVALID_ENTITY
|
|
REPEAT cnt i
|
|
IF (array[iSearchIndex].eState = GGSM_ENTITY_STATE_NONE)
|
|
ind = iSearchIndex
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
iSearchIndex = (iSearchIndex + 1) % cnt
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets a number of free entity
|
|
/// PARAMS:
|
|
/// array - array of entity
|
|
/// iNumProjectiles - # of desired entity
|
|
/// iArray - Array of ints with entity indexes in
|
|
/// iSearchIndex - Index in array to search for
|
|
/// RETURNS:
|
|
/// # of entity it could get
|
|
FUNC INT GGSM_GET_FREE_ENTITIES(GGSM_ENTITY &array[], INT iNumEntities, INT &iArray[], INT &iSearchIndex)
|
|
INT i
|
|
INT iEntitiesFound
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
// stops any overflow nonsense
|
|
iSearchIndex = ABSI(iSearchIndex) % cnt
|
|
|
|
REPEAT cnt i
|
|
IF (array[iSearchIndex].eState = GGSM_ENTITY_STATE_NONE)
|
|
iArray[iEntitiesFound] = iSearchIndex
|
|
iEntitiesFound ++
|
|
ENDIF
|
|
|
|
iSearchIndex = (iSearchIndex + 1) % cnt
|
|
|
|
IF (iNumEntities = iEntitiesFound) OR (iEntitiesFound = COUNT_OF(iArray))
|
|
RETURN iEntitiesFound
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN iEntitiesFound
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the index of the closest entity to a position
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// vPos - position to check
|
|
/// RETURNS:
|
|
///
|
|
FUNC INT GGSM_GET_CLOSEST_ENTITY_INDEX(GGSM_ENTITY &array[], VECTOR_2D vPos)
|
|
INT i
|
|
INT ind = GGSM_INVALID_ENTITY
|
|
FLOAT fDist
|
|
FLOAT fMaxDist = MAX_FLOAT
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
IF (array[i].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
fDist = VECTOR_2D_DIST2(array[i].sWorld.vPosition, vPos)
|
|
IF (fDist < fMaxDist)
|
|
fMaxDist = fDist
|
|
ind = i
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN ind
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the index of the closest entity to a position
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// vPos - position to check
|
|
/// RETURNS:
|
|
///
|
|
FUNC INT GGSM_GET_CLOSEST_ENEMY_ENTITY_INDEX(GGSM_ENTITY &array[], VECTOR_2D vPos, BOOL bAllied)
|
|
INT i
|
|
INT ind = GGSM_INVALID_ENTITY
|
|
FLOAT fDist
|
|
FLOAT fMaxDist = MAX_FLOAT
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
IF (array[i].eState = GGSM_ENTITY_STATE_ALIVE) AND (IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) != bAllied)
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
fDist = VECTOR_2D_DIST2(array[i].sCollider.sAABB.vCenter, vPos)
|
|
IF (fDist < fMaxDist)
|
|
fMaxDist = fDist
|
|
ind = i
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN ind
|
|
ENDFUNC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY GROUP FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
/// PURPOSE:
|
|
/// Resets Entity Group
|
|
/// PARAMS:
|
|
/// group -
|
|
PROC GGSM_RESET_ENTITY_GROUP(GGSM_ENTITY_GROUP &group)
|
|
group.eFlags = GGSM_GROUP_BIT_NONE
|
|
group.iLeader = GGSM_INVALID_ENTITY
|
|
group.iMemberBitSet = 0
|
|
group.iMembersToCreate = 0
|
|
group.iFormSpawnBitSet = 0
|
|
group.iMembersOnStageBitSet = 0
|
|
group.iActiveCount = 0
|
|
group.fDistCounter = 0.0
|
|
GGSM_FORMATION_SET_TYPE(group.sFormSettings, GGSM_FORMATION_NONE)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if group is running
|
|
/// PARAMS:
|
|
/// group -
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL GGSM_ENTITY_GROUP_IS_RUNNING(GGSM_ENTITY_GROUP &group)
|
|
RETURN IS_BITMASK_ENUM_AS_ENUM_SET(group.eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if group has finished (all members are dead)
|
|
/// PARAMS:
|
|
/// group -
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL GGSM_ENTITY_GROUP_HAS_GROUP_FINISHED(GGSM_ENTITY_GROUP &group)
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(group.eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN (group.iMembersToCreate = 0) AND (group.iActiveCount = 0)
|
|
ENDFUNC
|
|
|
|
PROC GGSM_DEACTIVATE_ENTITY_GROUP(GGSM_ENTITY_GROUP &group)
|
|
#IF IS_DEBUG_BUILD
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_DEACTIVATE_ENTITY_GROUP - GROUP:", group.iGroupID)
|
|
#ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
ENDPROC
|
|
|
|
PROC GGSM_SET_ENTITY_GROUP_FLAGS(GGSM_ENTITY_GROUP &group, GGSM_GROUP_BIT eFlags)
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, eFlags)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Activates and entity group
|
|
/// PARAMS:
|
|
/// group - group
|
|
/// iFlags - flags entity to create
|
|
/// iMembersLeftToCreate -
|
|
PROC GGSM_ACTIVATE_ENTITY_GROUP(GGSM_ENTITY_GROUP &group, GGSM_GROUP_BIT eFlags = GGSM_GROUP_BIT_NONE, INT iMembersLeftToCreate = 0)
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
group.eFlags = eFlags
|
|
group.iMembersToCreate = iMembersLeftToCreate
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Activates groups as formation
|
|
/// PARAMS:
|
|
/// group -
|
|
/// eSettings -
|
|
PROC GGSM_ACTIVATE_ENTITY_GROUP_AS_FORMATION(GGSM_ENTITY_GROUP &group, GGSM_FORMATION_DATA &eSettings)
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
group.sFormSettings = eSettings
|
|
group.iMembersToCreate = eSettings.iFormationMembers
|
|
group.fDistCounter = FMAX(ABSF(spriteSize.x), ABSF(spriteSize.y)) * 1.5
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_IS_FORMATION)
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_END_WHEN_ALL_OFFSCREEN)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ACTIVATE_ENTITY_GROUP_AS_FORMATION - GROUP:", group.iGroupID,
|
|
" TYPE:", GGSM_FORMATION_TYPE_TO_STRING(GGSM_FORMATION_GET_TYPE(group.sFormSettings)),
|
|
" MOVE PATTERN:", GGSM_MOVEMENT_TYPE_TO_STRING(GGSM_FORMATION_GET_MOVEMENT_TYPE(group.sFormSettings)),
|
|
" #:", GGSM_FORMATION_GET_MEMBER_COUNT(group.sFormSettings))
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets a group array
|
|
/// PARAMS:
|
|
/// array -
|
|
PROC GGSM_RESET_ENTITY_GROUP_ARRAY(GGSM_ENTITY_GROUP &array[])
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
array[i].iGroupID = i
|
|
GGSM_RESET_ENTITY_GROUP(array[i])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Searchs for a free entity group
|
|
/// PARAMS:
|
|
/// array -
|
|
/// RETURNS:
|
|
/// Index into group array - if no free group this returns -1
|
|
FUNC INT GGSM_GET_FREE_ENTITY_GROUP(GGSM_ENTITY_GROUP &array[])
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
RETURN i
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN GGSM_INVALID_GROUP_ID
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Adds an Entity to a group
|
|
/// PARAMS:
|
|
/// ent - entity to add
|
|
/// iGroupID - group id to add to
|
|
PROC GGSM_ADD_ENTITY_TO_GROUP(GGSM_ENTITY &ent, INT iGroupID)
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (sGGSMData.sEntityGroup[iGroupID].iLeader = GGSM_INVALID_ENTITY)
|
|
sGGSMData.sEntityGroup[iGroupID].iLeader = iArrayIndex
|
|
ENDIF
|
|
|
|
IF NOT IS_BIT_SET(sGGSMData.sEntityGroup[iGroupID].iMemberBitSet, iArrayIndex)
|
|
SET_BIT(sGGSMData.sEntityGroup[iGroupID].iMemberBitSet, iArrayIndex)
|
|
SET_BIT(sGGSMData.sEntityGroup[iGroupID].iMembersOnStageBitSet, iArrayIndex)
|
|
sGGSMData.sEntityGroup[iGroupID].iActiveCount ++
|
|
sGGSMData.sEntityGroup[iGroupID].iMembersToCreate --
|
|
IF (sGGSMData.sEntityGroup[iGroupID].iMembersToCreate < 0)
|
|
sGGSMData.sEntityGroup[iGroupID].iMembersToCreate = 0
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_END_WHEN_ALL_OFFSCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MINIGAME, "GGSM_ADD_ENTITY_TO_GROUP #", iGroupID, " - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(ent.eType), " ARRAY INDEX:", iArrayIndex)
|
|
GGSM_ENTITY_SET_GROUP_ID(ent, iGroupID)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Removes entity from a group - This will shutdown the group if there are no members left
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_REMOVE_ENTITY_FROM_GROUP(GGSM_ENTITY &ent)
|
|
INT grp = GGSM_ENTITY_GET_GROUP_ID(ent)
|
|
IF (grp = GGSM_INVALID_GROUP_ID)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
|
|
IF IS_BIT_SET(sGGSMData.sEntityGroup[grp].iMemberBitSet, iArrayIndex)
|
|
CLEAR_BIT(sGGSMData.sEntityGroup[grp].iMemberBitSet, iArrayIndex)
|
|
CLEAR_BIT(sGGSMData.sEntityGroup[grp].iMembersOnStageBitSet, iArrayIndex)
|
|
sGGSMData.sEntityGroup[grp].iActiveCount --
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_MINIGAME, "GGSM_REMOVE_ENTITY_FROM_GROUP #", grp, " - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(ent.eType), " ARRAY INDEX:", iArrayIndex)
|
|
GGSM_ENTITY_SET_GROUP_ID(ent, GGSM_INVALID_GROUP_ID)
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[grp].eFlags, GGSM_GROUP_BIT_IS_FORMATION)
|
|
IF (sGGSMData.sEntityGroup[grp].iActiveCount = 0)
|
|
GGSM_DEACTIVATE_ENTITY_GROUP(sGGSMData.sEntityGroup[grp])
|
|
ENDIF
|
|
ELIF (sGGSMData.sEntityGroup[grp].iMembersToCreate = 0)
|
|
IF (sGGSMData.sEntityGroup[grp].iActiveCount = 0)
|
|
GGSM_DEACTIVATE_ENTITY_GROUP(sGGSMData.sEntityGroup[grp])
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
//-------------------------------------------------
|
|
// QUERY FUNCTION
|
|
//-------------------------------------------------
|
|
FUNC BOOL GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
IF (sGGSMData.iPlayerShipIndex = GGSM_INVALID_ENTITY)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].eState != GGSM_ENTITY_STATE_NONE)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_IS_PLAYER_SHIP_ALIVE()
|
|
IF (sGGSMData.iPlayerShipIndex = GGSM_INVALID_ENTITY)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_DOES_PLAYER_DECOY_EXIST()
|
|
IF (sGGSMData.iPlayerDecoyIndex = GGSM_INVALID_ENTITY)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (sGGSMData.sEntities[sGGSMData.iPlayerDecoyIndex].eState != GGSM_ENTITY_STATE_NONE)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_DOES_PLAYER_SHIELD_EXIST()
|
|
IF (sGGSMData.iPlayerShieldIndex = GGSM_INVALID_ENTITY)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (sGGSMData.sEntities[sGGSMData.iPlayerShieldIndex].eState != GGSM_ENTITY_STATE_NONE)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_IS_PLAYER_TOTALLY_DEFEATED()
|
|
IF GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN (sGGSMData.iPlayerLives = 0)
|
|
ENDFUNC
|
|
|
|
PROC GGSM_SET_PLAYER_INVUNERABLE()
|
|
IF GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INITIAL_INV_TIME
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
//-------------------------------------------------
|
|
// PROJECTILE ARRAY FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
/// PURPOSE:
|
|
/// Sets all projectiles to be inactive
|
|
/// PARAMS:
|
|
/// array - array of projectiles
|
|
PROC GGSM_RESET_PROJECTILE_ARRAY(GGSM_PROJECTILE &array[])
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
REPEAT cnt i
|
|
array[i].eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
array[i].fTimer = 0
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the next free projectile index
|
|
/// PARAMS:
|
|
/// array - projecile array
|
|
/// ind - Index of the next free index
|
|
/// iSearchIndex - Index to start searching from
|
|
/// RETURNS:
|
|
/// TRUE if projectile can be found
|
|
FUNC BOOL GGSM_GET_FREE_PROJECTILE(GGSM_PROJECTILE &array[], INT &ind, INT &iSearchIndex)
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
// stops any overflow nonsense
|
|
iSearchIndex = ABSI(iSearchIndex) % cnt
|
|
|
|
ind = GGSM_INVALID_PROJECTILE
|
|
REPEAT cnt i
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(array[iSearchIndex].eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
ind = iSearchIndex
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
iSearchIndex = (iSearchIndex + 1) % cnt
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets a number of free projectiles
|
|
/// PARAMS:
|
|
/// array - array of projectiles
|
|
/// iNumProjectiles - # of desired projectiles
|
|
/// iArray - Array of ints with projectile indexes in
|
|
/// iSearchIndex - Index in array to search for
|
|
/// RETURNS:
|
|
/// # of projectiles it could get
|
|
FUNC INT GGSM_GET_FREE_PROJECTILES(GGSM_PROJECTILE &array[], INT iNumProjectiles, INT &iArray[], INT &iSearchIndex)
|
|
INT i
|
|
INT iProjectilesFound
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
// stops any overflow nonsense
|
|
iSearchIndex = ABSI(iSearchIndex) % cnt
|
|
|
|
REPEAT cnt i
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(array[iSearchIndex].eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
iArray[iProjectilesFound] = iSearchIndex
|
|
iProjectilesFound ++
|
|
ENDIF
|
|
|
|
iSearchIndex = (iSearchIndex + 1) % cnt
|
|
|
|
IF (iProjectilesFound = iNumProjectiles) OR (iProjectilesFound = cnt)
|
|
RETURN iProjectilesFound
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN 0
|
|
ENDFUNC
|
|
|
|
//-------------------------------------------------
|
|
// PROJECTILE FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
FUNC VECTOR_2D GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
IF (sGGSMData.iPlayerDecoyIndex != GGSM_INVALID_ENTITY)
|
|
RETURN sGGSMData.sEntities[sGGSMData.iPlayerDecoyIndex].sWorld.vPosition
|
|
ENDIF
|
|
|
|
IF (sGGSMData.iPlayerShipIndex != GGSM_INVALID_ENTITY)
|
|
RETURN sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].sWorld.vPosition
|
|
ENDIF
|
|
|
|
RETURN INIT_VECTOR_2D(0, 0)
|
|
ENDFUNC
|
|
|
|
FUNC INT GGSM_PROJECTILE_GET_TARGET_INDEX(GGSM_PROJECTILE &ent)
|
|
RETURN ent.iTargetIndex
|
|
ENDFUNC
|
|
|
|
PROC GGSM_PROJECTILE_SET_TARGET_INDEX(GGSM_PROJECTILE &ent, INT i)
|
|
ent.iTargetIndex = i
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_PROJECTILE_HAS_COLLISION(GGSM_PROJECTILE &ent)
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_HAS_NO_COLLISION)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Initializes projectile based on data
|
|
/// PARAMS:
|
|
/// ent - projectile to initialize
|
|
/// eType - projectile type
|
|
/// vPos - world position of projectile
|
|
/// fRot - world rotation of projectile
|
|
PROC GGSM_PROJECTILE_INIT(GGSM_PROJECTILE &ent, GGSM_PROJECTILE_TYPE eType, VECTOR_2D vPos, FLOAT fRot, BOOL bIsFriendly = FALSE)
|
|
GGSM_PROJECTILE_DATA dat = GGSM_PROJECTILE_DATA_GET(eType)
|
|
VECTOR_2D dir
|
|
|
|
ent.eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
ent.eType = eType
|
|
ent.fTimer = 0.0
|
|
|
|
ent.fDistTravelled = 0
|
|
ent.fLength = dat.fLength
|
|
ent.fSpeed = dat.fBaseSpeed
|
|
ent.sCollider.sData.fColRadius = dat.fRadius
|
|
ent.vDirection = GGSM_GET_VECTOR_FROM_HEADING(fRot)
|
|
ent.iPackedOrigin = GGSM_PACK_VECTOR_2D_TO_INT(vPos)
|
|
ent.iTargetIndex = GGSM_INVALID_ENTITY
|
|
|
|
IF (ent.fLength = 0.0)
|
|
ent.sCollider.sData.eType = GGSM_COLLISION_CIRCLE
|
|
ent.sCollider.sData.vCollisionVectors[0] = vPos
|
|
ent.sCollider.sData.vCollisionVectors[1] = vPos
|
|
ELSE
|
|
dir.x = ent.vDirection.x * ent.fLength
|
|
dir.y = ent.vDirection.y * ent.fLength
|
|
|
|
ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE
|
|
ent.sCollider.sData.vCollisionVectors[0] = vPos
|
|
ent.sCollider.sData.vCollisionVectors[1].x = vPos.x + dir.x
|
|
ent.sCollider.sData.vCollisionVectors[1].y = vPos.y + dir.y
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
GGSM_COLLIDER_CALCULATE_AABB(ent.sCollider)
|
|
|
|
IF (bIsFriendly)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
ENDIF
|
|
|
|
IF (eType = GGSM_PROJECTILE_HOMING_ROCKET)
|
|
ent.iTargetIndex = GGSM_GET_CLOSEST_ENEMY_ENTITY_INDEX(sGGSMData.sEntities, vPos, bIsFriendly)
|
|
IF (ent.iTargetIndex != GGSM_INVALID_ENTITY)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_HOMING)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (eType = GGSM_PROJECTILE_ENEMY_CLUSTER_BOMB) OR (eType = GGSM_PROJECTILE_DANK_CLUSTERBOMB)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_CLUSTER_BOMB)
|
|
ELIF (eType = GGSM_PROJECTILE_ENEMY_BEAM)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_LOCKED_TO_PARENT)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_BEAM_WEAPON)
|
|
ELIF (eType = GGSM_PROJECTILE_DANK_HOMING_ROCKET)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_DELAYED_HOMING)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_PROJECTILE_CREATE_ENEMY_RADIAL_SPREAD(GGSM_PROJECTILE_TYPE eType, VECTOR_2D vPos, INT iCount, FLOAT fRot = 0.0, BOOL bTargetPlayer = FALSE)
|
|
INT ind, cnt
|
|
INT iProjList[16]
|
|
FLOAT fAngle = fRot
|
|
FLOAT fAngDiff = 360.0 / TO_FLOAT(iCount)
|
|
VECTOR_2D vec
|
|
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, iCount, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
IF (cnt = 0)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (bTargetPlayer)
|
|
vec = SUBTRACT_VECTOR_2D(GGSM_GET_TARGET_AT_PLAYER_POSITION(), vPos)
|
|
fAngle = GET_HEADING_FROM_VECTOR_2D(vec.x, vec.y)
|
|
ENDIF
|
|
|
|
REPEAT cnt ind
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[ind]], eType, vPos, fAngle, FALSE)
|
|
fAngle += fAngDiff
|
|
ENDREPEAT
|
|
|
|
GGSM_PROJECTILE_DATA dat = GGSM_PROJECTILE_DATA_GET(eType)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(dat.eProjSound, vPos)
|
|
ENDPROC
|
|
|
|
PROC GGSM_PROJECTILE_CREATE_ENEMY_CONE_SPREAD(GGSM_PROJECTILE_TYPE eType, VECTOR_2D vPos, FLOAT fSpreadAngle, INT iCount, BOOL bTargetPlayer = FALSE)
|
|
INT ind, cnt
|
|
INT iProjList[16]
|
|
FLOAT fBaseAngle, fAngle
|
|
FLOAT fAngDiff = 360.0 / TO_FLOAT(iCount)
|
|
VECTOR_2D vec
|
|
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, iCount, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
IF (cnt = 0)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (bTargetPlayer)
|
|
vec = SUBTRACT_VECTOR_2D(GGSM_GET_TARGET_AT_PLAYER_POSITION(), vPos)
|
|
fBaseAngle = GET_HEADING_FROM_VECTOR_2D(vec.x, vec.y)
|
|
ENDIF
|
|
|
|
fAngDiff = fSpreadAngle / TO_FLOAT(iCount - 1)
|
|
fBaseAngle -= (fSpreadAngle / 2.0)
|
|
|
|
REPEAT cnt ind
|
|
fAngle = fBaseAngle + (TO_FLOAT(ind) * fAngDiff)
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[ind]], eType, vPos, fAngle, FALSE)
|
|
ENDREPEAT
|
|
|
|
GGSM_PROJECTILE_DATA dat = GGSM_PROJECTILE_DATA_GET(eType)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(dat.eProjSound, vPos)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Gets the speed multiplied by timescale
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// RETURNS:
|
|
///
|
|
FUNC FLOAT GGSM_GET_PROJECTILE_SPEED(GGSM_PROJECTILE &ent)
|
|
GGSM_PROJECTILE_DATA dat = GGSM_PROJECTILE_DATA_GET(ent.eType)
|
|
FLOAT spd = dat.fBaseSpeed
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
spd *= sGGSMData.fTimeScale
|
|
ENDIF
|
|
|
|
RETURN spd
|
|
ENDFUNC
|
|
|
|
PROC GGSM_REFLECT_PROJECTILE(GGSM_PROJECTILE &ent)
|
|
VECTOR_2D tmp
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_FIRED_BY_PLAYER)
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
ENDIF
|
|
|
|
// remove any homing capability
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_PROJECTILE_BIT_IS_HOMING)
|
|
ent.iTargetIndex = GGSM_INVALID_ENTITY
|
|
|
|
// make it face the other way
|
|
tmp = ent.sCollider.sData.vCollisionVectors[0]
|
|
ent.sCollider.sData.vCollisionVectors[0] = ent.sCollider.sData.vCollisionVectors[1]
|
|
ent.sCollider.sData.vCollisionVectors[1] = tmp
|
|
|
|
FLOAT ang = GET_HEADING_FROM_VECTOR_2D(ent.vDirection.x, ent.vDirection.y)
|
|
|
|
IF GET_RANDOM_BOOL()
|
|
ang += GET_RANDOM_FLOAT_IN_RANGE(-190.0, -181.0)
|
|
ELSE
|
|
ang += GET_RANDOM_FLOAT_IN_RANGE(-179.0, -160.0)
|
|
ENDIF
|
|
|
|
ent.vDirection = GGSM_GET_VECTOR_FROM_HEADING(ang)
|
|
|
|
ent.fDistTravelled = 0.0
|
|
ENDPROC
|
|
|
|
PROC GGSM_REFLECT_ENEMY_PROJECTILES()
|
|
INT i
|
|
|
|
REPEAT GGSM_MAX_PROJECTILES i
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sProjectiles[i].eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
GGSM_REFLECT_PROJECTILE(sGGSMData.sProjectiles[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Returns true if the bullet was destroyed and not turned into something else
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL GGSM_PROJECTILE_TAKE_DAMAGE(GGSM_PROJECTILE &ent)
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED)
|
|
GGSM_PROJECTILE_DATA dat
|
|
|
|
IF (ent.eType = GGSM_PROJECTILE_EXP_SHELL)
|
|
GGSM_PROJECTILE_INIT(ent, GGSM_PROJECTILE_BOMB_EXPLOSION, ent.sCollider.sAABB.vCenter, 0, bIsAllied)
|
|
dat = GGSM_PROJECTILE_DATA_GET(GGSM_PROJECTILE_BOMB_EXPLOSION)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(dat.eProjSound, ent.sCollider.sAABB.vCenter)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_PROJECTILE_BOMB_EXPLOSION)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_CLUSTER_BOMB) AND NOT (bIsAllied)
|
|
GGSM_PROJECTILE_CREATE_ENEMY_RADIAL_SPREAD(GGSM_PROJECTILE_ENEMY_SHOT, ent.sCollider.sAABB.vCenter, 5, 0, TRUE)
|
|
ENDIF
|
|
|
|
ent.eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_ACID(GGSM_PROJECTILE &ent)
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
|
|
IF (ent.fDistTravelled > 300.0)
|
|
ent.vDirection = LERP_VECTOR_2D(ent.vDirection, INIT_VECTOR_2D(-1, 0), 0.25)
|
|
ENDIF
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_HOMING(GGSM_PROJECTILE &ent)
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
VECTOR_2D dir, ndir
|
|
|
|
IF (ent.iTargetIndex != GGSM_INVALID_ENTITY)
|
|
IF (sGGSMData.sEntities[ent.iTargetIndex].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
dir = SUBTRACT_VECTOR_2D(sGGSMData.sEntities[ent.iTargetIndex].sCollider.sAABB.vCenter, ent.sCollider.sData.vCollisionVectors[0])
|
|
ndir = NORMALISE_VECTOR_2D(dir)
|
|
ent.vDirection = LERP_VECTOR_2D(ent.vDirection, ndir, 0.25)
|
|
ELSE
|
|
ent.iTargetIndex = GGSM_INVALID_ENTITY
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_DELAYED_HOMING(GGSM_PROJECTILE &ent)
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
VECTOR_2D dir, ndir
|
|
INT ind
|
|
|
|
IF (ent.fDistTravelled > 150.0) AND (ent.iTargetIndex = GGSM_INVALID_ENTITY)
|
|
ent.iTargetIndex = GGSM_GET_CLOSEST_ENEMY_ENTITY_INDEX(sGGSMData.sEntities, ent.sCollider.sData.vCollisionVectors[0], IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED))
|
|
ENDIF
|
|
|
|
IF (ent.iTargetIndex != GGSM_INVALID_ENTITY)
|
|
IF (sGGSMData.sEntities[ent.iTargetIndex].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
dir = SUBTRACT_VECTOR_2D(sGGSMData.sEntities[ent.iTargetIndex].sCollider.sAABB.vCenter, ent.sCollider.sData.vCollisionVectors[0])
|
|
ndir = NORMALISE_VECTOR_2D(dir)
|
|
ent.vDirection = LERP_VECTOR_2D(ent.vDirection, ndir, 0.125)
|
|
ELSE
|
|
ent.iTargetIndex = GGSM_INVALID_ENTITY
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
|
|
IF (ent.fDistTravelled > 1200.0)
|
|
IF GGSM_GET_FREE_FXSPRITE(sGGSMData.sFXSprite, ind, sGGSMData.iExplosionSearchIndex)
|
|
GGSM_FXSPRITE_INIT_ANIMATED(sGGSMData.sFXSprite[ind], ent.sCollider.sAABB.vCenter, GGSM_SPRITE_ANIM_EXPLOSION, 2.0)
|
|
GGSM_FXSPRITE_SET_PHYSICAL_RADIUS(sGGSMData.sFXSprite[ind], ent.fLength * 2.0)
|
|
ENDIF
|
|
|
|
ent.eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_SINWAVE(GGSM_PROJECTILE &ent)
|
|
FLOAT fPeriod, fWaveHeight = 44.0
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
|
|
// move forward
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0] = GGSM_UNPACK_VECTOR_2D(ent.iPackedOrigin)
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * ent.fDistTravelled)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * ent.fDistTravelled)
|
|
|
|
// horizontal displacement - get the perpendicular
|
|
fPeriod = TO_FLOAT(FLOOR(ent.fDistTravelled) % FLOOR(600.0)) / 600.0
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_NEG_SINEWAVE)
|
|
fWaveHeight *= -1.0
|
|
ENDIF
|
|
spd = SIN(fPeriod * 360.0) * fWaveHeight
|
|
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_STRAIGHT(GGSM_PROJECTILE &ent)
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE_MARINE_BOMB(GGSM_PROJECTILE &ent)
|
|
INT ind
|
|
FLOAT spd = 0 +@ GGSM_GET_PROJECTILE_SPEED(ent)
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sCollider.sData.vCollisionVectors[0].x += (ent.vDirection.x * spd)
|
|
ent.sCollider.sData.vCollisionVectors[0].y += (ent.vDirection.y * spd)
|
|
ent.sCollider.sData.vCollisionVectors[1] = ent.sCollider.sData.vCollisionVectors[0]
|
|
|
|
IF (ent.sCollider.sData.eType = GGSM_COLLISION_CAPSULE)
|
|
ent.sCollider.sData.vCollisionVectors[1].x += (ent.vDirection.x * ent.fLength)
|
|
ent.sCollider.sData.vCollisionVectors[1].y += (ent.vDirection.y * ent.fLength)
|
|
ENDIF
|
|
|
|
IF (ent.sCollider.sData.vCollisionVectors[0].x < 350.0) OR (ent.sCollider.sData.vCollisionVectors[0].x > 1580.0) OR
|
|
(ent.sCollider.sData.vCollisionVectors[0].y < 110.0) OR (ent.sCollider.sData.vCollisionVectors[0].y > 990.0)
|
|
GGSM_PROJECTILE_CREATE_ENEMY_CONE_SPREAD(GGSM_PROJECTILE_ENEMY_SHOT, ent.sCollider.sAABB.vCenter, 90.0, GET_RANDOM_INT_IN_RANGE(3, 5), TRUE)
|
|
|
|
IF GGSM_GET_FREE_FXSPRITE(sGGSMData.sFXSprite, ind, sGGSMData.iExplosionSearchIndex)
|
|
GGSM_FXSPRITE_INIT_ANIMATED(sGGSMData.sFXSprite[ind], ent.sCollider.sAABB.vCenter, GGSM_SPRITE_ANIM_EXPLOSION, 2.0)
|
|
GGSM_FXSPRITE_SET_PHYSICAL_RADIUS(sGGSMData.sFXSprite[ind], ent.fLength * 2.0)
|
|
ENDIF
|
|
|
|
ent.eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_PROJECTILE_UPDATE_BOMB_EXPLOSION(GGSM_PROJECTILE &ent)
|
|
UNUSED_PARAMETER(ent)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update projectile and transform collision
|
|
/// PARAMS:
|
|
/// ent - projectile to update
|
|
PROC GGSM_PROJECTILE_UPDATE(GGSM_PROJECTILE &ent)
|
|
// update timer
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED))
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_PROJECTILES_ACTIVE)
|
|
ent.fTimer += sGGSMData.fDeltaTime
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_ENEMY_PROJECTILES_ACTIVE)
|
|
ent.fTimer += (sGGSMData.fDeltaTime * sGGSMData.fTimeScale)
|
|
|
|
IF GGSM_IS_PLAYER_SHIP_ALIVE()
|
|
IF (GET_GAME_TIMER() > sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].iInvTimeMS)
|
|
IF VECTOR_2D_DIST2(ent.sCollider.sAABB.vCenter, sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].sWorld.vPosition) < (sGGSMData.fGrazeRadius * sGGSMData.fGrazeRadius)
|
|
sGGSMData.bGrazed = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
sGGSMData.iEnemyProjectilesActive ++
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_PROJECTILE_ACID)
|
|
GGSM_PROJECTILE_UPDATE_ACID(ent)
|
|
ELIF (ent.eType = GGSM_PROJECTILE_BOMB_EXPLOSION)
|
|
GGSM_PROJECTILE_UPDATE_BOMB_EXPLOSION(ent)
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_SINEWAVE)
|
|
GGSM_PROJECTILE_UPDATE_SINWAVE(ent)
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_HOMING)
|
|
GGSM_PROJECTILE_UPDATE_HOMING(ent)
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_DELAYED_HOMING)
|
|
GGSM_PROJECTILE_UPDATE_DELAYED_HOMING(ent)
|
|
ELIF (ent.eType = GGSM_PROJECTILE_MARINE_LAUNCHER)
|
|
GGSM_PROJECTILE_UPDATE_MARINE_BOMB(ent)
|
|
ELSE
|
|
GGSM_PROJECTILE_UPDATE_STRAIGHT(ent)
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_PROJECTILE_BIT_IS_CLUSTER_BOMB)
|
|
IF (VECTOR_2D_DIST2(ent.sCollider.sData.vCollisionVectors[0], GGSM_GET_TARGET_AT_PLAYER_POSITION()) < (400.0 * 400.0)) OR (ent.fDistTravelled > 700.0)
|
|
GGSM_PROJECTILE_TAKE_DAMAGE(ent)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
sGGSMData.iProjectilesActive ++
|
|
GGSM_COLLIDER_CALCULATE_AABB(ent.sCollider)
|
|
IF NOT GGSM_IS_COLLIDER_AABB_ON_SCREEN(ent.sCollider)
|
|
ent.eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
EXIT
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update the projectile array
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// RETURNS:
|
|
/// # of active projectiles
|
|
FUNC BOOL GGSM_UPDATE_PROJECTILE_ARRAY(GGSM_PROJECTILE &array[])
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
BOOL bActiveCheck = FALSE
|
|
|
|
sGGSMData.iProjectilesActive = 0
|
|
sGGSMData.iEnemyProjectilesActive = 0
|
|
REPEAT cnt i
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
GGSM_PROJECTILE_UPDATE(array[i])
|
|
bActiveCheck = TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF (sGGSMData.iProjectilesActive > sGGSMData.iMaxProjectilesActive)
|
|
sGGSMData.iMaxProjectilesActive = sGGSMData.iProjectilesActive
|
|
ENDIF
|
|
|
|
RETURN bActiveCheck
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Update the projectile array
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// RETURNS:
|
|
/// # of active projectiles
|
|
PROC GGSM_DESTROY_ALL_FACTION_BULLETS(GGSM_PROJECTILE &array[], BOOL bAllied)
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
REPEAT cnt i
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_PROJECTILE_BIT_ACTIVE)
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED) = bAllied)
|
|
array[i].eFlags = GGSM_PROJECTILE_BIT_NONE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY QUERY FUNCTIONS
|
|
//-------------------------------------------------
|
|
FUNC BOOL GGSM_ENTITY_IS_MAIN_BOSS_SECTION(GGSM_ENTITY &ent)
|
|
IF (ent.eType = GGSM_ENTITY_BOSS_BREAD_FACE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_BOSS_GRANANA)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_BOSS_MARINE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_BOSS_SMOOTHIE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_BOSS_DR_DANK_TOP)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
FUNC BOOL GGSM_ENTITY_IS_STRONG(GGSM_ENTITY &ent)
|
|
IF GGSM_ENTITY_IS_MAIN_BOSS_SECTION(ent)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
SWITCH (ent.eType)
|
|
CASE GGSM_ENTITY_ARMOUR_FRUITBOWL
|
|
CASE GGSM_ENTITY_BANANASLICE_FRONT
|
|
CASE GGSM_ENTITY_BANANASLICE
|
|
CASE GGSM_ENTITY_BANANASLICE_BACK
|
|
CASE GGSM_ENTITY_BOSS_BREAD_FACE
|
|
CASE GGSM_ENTITY_BOSS_BREAD_BOTTOM_LEFT
|
|
CASE GGSM_ENTITY_BOSS_BREAD_BOTTOM_RIGHT
|
|
CASE GGSM_ENTITY_BOSS_BREAD_TOP_LEFT
|
|
CASE GGSM_ENTITY_BOSS_BREAD_TOP_RIGHT
|
|
CASE GGSM_ENTITY_BANANASPLIT_1
|
|
CASE GGSM_ENTITY_BANANASPLIT_2
|
|
CASE GGSM_ENTITY_BANANASPLIT_3
|
|
CASE GGSM_ENTITY_BANANASPLIT_4
|
|
CASE GGSM_ENTITY_BOSS_MARINE
|
|
CASE GGSM_ENTITY_BOSS_GRANANA
|
|
CASE GGSM_ENTITY_BOSS_GRANANA_HAIR
|
|
CASE GGSM_ENTITY_BOSS_DR_DANK_TOP
|
|
CASE GGSM_ENTITY_BOSS_DR_DANK_MIDDLE
|
|
CASE GGSM_ENTITY_BOSS_DR_DANK_BOTTOM
|
|
CASE GGSM_ENTITY_BOSS_SMOOTHIE
|
|
RETURN TRUE
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC INT GGSM_ENTITY_GET_PERCENTAGE_OF_HEALTH(GGSM_ENTITY &ent, FLOAT fPc)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
RETURN CEIL(TO_FLOAT(dat.iMaxHP) * (fpc / 100.0))
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_HAS_COLLISION(GGSM_ENTITY &ent)
|
|
IF (ent.eState != GGSM_ENTITY_STATE_ALIVE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_CAN_COLLIDE_WITH(GGSM_ENTITY &ent, GGSM_ENTITY &ent2)
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = IS_BITMASK_ENUM_AS_ENUM_SET(ent2.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED))
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT GGSM_ENTITY_HAS_COLLISION(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN GGSM_ENTITY_HAS_COLLISION(ent2)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_CAN_COLLIDE_WITH_PROJECTILE(GGSM_ENTITY &ent, GGSM_PROJECTILE &proj)
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = IS_BITMASK_ENUM_AS_ENUM_SET(proj.eFlags, GGSM_PROJECTILE_BIT_IS_PLAYER_ALLIED))
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT GGSM_ENTITY_HAS_COLLISION(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN GGSM_PROJECTILE_HAS_COLLISION(proj)
|
|
ENDFUNC
|
|
|
|
FUNC FLOAT GGSM_ENTITY_GET_HP_PERCENTAGE(GGSM_ENTITY &ent)
|
|
IF (ent.eState != GGSM_ENTITY_STATE_ALIVE)
|
|
RETURN 0.0
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
RETURN TO_FLOAT(ent.iHP) / TO_FLOAT(dat.iMaxHP)
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_SET_ANIM_FRAME(GGSM_ENTITY &ent, INT iAnimFrame = -1, BOOL bStopAnim = FALSE)
|
|
IF (iAnimFrame = -1)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
ent.fAnimFrame = TO_FLOAT(dat.iDefaultAnimFrame)
|
|
ELSE
|
|
ent.fAnimFrame = TO_FLOAT(iAnimFrame)
|
|
ENDIF
|
|
|
|
IF (bStopAnim)
|
|
ent.eSpriteAnim = GGSM_SPRITE_ANIM_NONE
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_ENTITY_SET_ANIMATION(GGSM_ENTITY &ent, GGSM_SPRITE_ANIM eType)
|
|
GGSM_SPRITE_ANIM_DATA data
|
|
|
|
IF (eType = GGSM_SPRITE_ANIM_NONE)
|
|
ent.eSpriteAnim = eType
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT GGSM_GET_SPRITE_ANIM_DATA(eType, data)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ent.eSpriteAnim = eType
|
|
ent.fAnimFrame = data.fStartFrame
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_DETACH_FROM_PARENT(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_SET_PARENT_INDEX(ent, GGSM_INVALID_ENTITY)
|
|
ent.sLocal = ent.sWorld
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY WEAPON FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_ENTITY_SET_WEAPON_STATE(GGSM_ENTITY &ent, GGSM_WEAPON_STATE eState, BOOL bResetTimer = TRUE)
|
|
ent.eWeaponState = eState
|
|
IF (bResetTimer)
|
|
ent.fWeaponTimer = 0
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_WEAPON(GGSM_ENTITY &ent, GGSM_WEAPON_TYPE eType)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
|
|
IF (eType = GGSM_WEAPON_DEFAULT)
|
|
eType = entData.eWeaponType
|
|
ENDIF
|
|
|
|
ent.eWeaponType = eType
|
|
ent.iWeaponShotCounter = 0
|
|
ent.iWeaponBurstCounter = 0
|
|
|
|
IF (ent.eWeaponType = GGSM_WEAPON_NONE)
|
|
EXIT
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC VECTOR_2D GGSM_ENTITY_GET_GUN_WORLD_POS(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
RETURN GGSM_TRANSFORM_LOCAL_POS_TO_WORLD_POS(ent.sWorld, entData.sGunPos.vPosition)
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_FIRE_WEAPON(GGSM_ENTITY &ent)
|
|
IF (ent.eWeaponType = GGSM_WEAPON_NONE) OR (ent.eWeaponType = GGSM_WEAPON_INVALID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.eStageFlags, GGSM_STAGE_BIT_DISABLE_WEAPONS)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
INT ind, cnt
|
|
FLOAT fBaseAngle
|
|
VECTOR_2D tgtPos, dir, shotPos
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
BOOL bIsRandomSpread = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_RANDOM_SPREAD)
|
|
|
|
// handle targeting
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
VECTOR_2D gunPos = GGSM_TRANSFORM_LOCAL_POS_TO_WORLD_POS(ent.sWorld, entData.sGunPos.vPosition)
|
|
fBaseAngle = ent.sWorld.fRotation + entData.sGunPos.fRotation
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED) AND NOT bIsAllied
|
|
tgtPos = GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
dir = SUBTRACT_VECTOR_2D(tgtPos, gunPos)
|
|
fBaseAngle = GET_HEADING_FROM_VECTOR_2D(dir.x, dir.y)
|
|
ENDIF
|
|
|
|
// get data from weapon
|
|
GGSM_WEAPON_DATA wpnData = GGSM_WEAPON_DATA_GET(ent.eWeaponType)
|
|
INT iNumShots = wpnData.iNumShots
|
|
BOOL bBurstDone
|
|
|
|
IF (ent.iNumShotsOverride > 0)
|
|
iNumShots = ent.iNumShotsOverride
|
|
ENDIF
|
|
|
|
IF (sGGSMData.bHardMode) AND (NOT bIsAllied) AND (iNumShots > 1)
|
|
iNumShots ++
|
|
ENDIF
|
|
|
|
FLOAT wSpread
|
|
INT iProjList[16]
|
|
FLOAT fAngle, fAngDiff = 360.0 / TO_FLOAT(iNumShots)
|
|
|
|
SWITCH (wpnData.eSpreadType)
|
|
CASE GGSM_SPREAD_LINEAR
|
|
IF GGSM_GET_FREE_PROJECTILE(sGGSMData.sProjectiles, ind, sGGSMData.iProjectileSearchIndex)
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[ind], wpnData.eProjectileType, gunPos, fBaseAngle, bIsAllied)
|
|
ent.iWeaponShotCounter ++
|
|
bBurstDone = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_SPREAD_RADIAL
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
fBaseAngle += (fAngDiff / 2.0)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, 1, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
fAngle = fBaseAngle + (TO_FLOAT(ent.iWeaponShotCounter) * fAngDiff)
|
|
IF (bIsRandomSpread)
|
|
fAngle = GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0)
|
|
ENDIF
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[0]], wpnData.eProjectileType, gunPos, fAngle, bIsAllied)
|
|
ent.iWeaponShotCounter ++
|
|
|
|
IF (ent.iWeaponShotCounter >= iNumShots)
|
|
bBurstDone = TRUE
|
|
ent.iWeaponShotCounter = 0
|
|
ENDIF
|
|
ELSE
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, iNumShots, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
REPEAT cnt ind
|
|
fAngle = fBaseAngle + (TO_FLOAT(ind) * fAngDiff)
|
|
IF (bIsRandomSpread)
|
|
fAngle = GET_RANDOM_FLOAT_IN_RANGE(0.0, 360.0)
|
|
ENDIF
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[ind]], wpnData.eProjectileType, gunPos, fAngle, bIsAllied)
|
|
ENDREPEAT
|
|
|
|
ent.iWeaponShotCounter = 0
|
|
bBurstDone = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_SPREAD_CONE
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
iNumShots ++
|
|
ENDIF
|
|
ENDIF
|
|
|
|
fAngDiff = wpnData.fSpreadValue / TO_FLOAT(iNumShots - 1)
|
|
fBaseAngle -= (wpnData.fSpreadValue / 2.0)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, 1, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
fAngle = fBaseAngle + (TO_FLOAT(ent.iWeaponShotCounter) * fAngDiff)
|
|
IF (bIsRandomSpread)
|
|
fAngle = fBaseAngle + (GET_RANDOM_FLOAT_IN_RANGE(0.0, TO_FLOAT(iNumShots)) * fAngDiff)
|
|
ENDIF
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[0]], wpnData.eProjectileType, gunPos, fAngle, bIsAllied)
|
|
ent.iWeaponShotCounter ++
|
|
|
|
IF (ent.iWeaponShotCounter >= iNumShots)
|
|
bBurstDone = TRUE
|
|
ent.iWeaponShotCounter = 0
|
|
ENDIF
|
|
ELSE
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, iNumShots, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
REPEAT cnt ind
|
|
fAngle = fBaseAngle + (TO_FLOAT(ind) * fAngDiff)
|
|
IF (bIsRandomSpread)
|
|
fAngle = fBaseAngle + (GET_RANDOM_FLOAT_IN_RANGE(0.0, TO_FLOAT(iNumShots)) * fAngDiff)
|
|
ENDIF
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[ind]], wpnData.eProjectileType, gunPos, fAngle, bIsAllied)
|
|
ent.iWeaponShotCounter = 0
|
|
bBurstDone = TRUE
|
|
ENDREPEAT
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_SPREAD_WAVE
|
|
IF GGSM_GET_FREE_PROJECTILE(sGGSMData.sProjectiles, ind, sGGSMData.iProjectileSearchIndex)
|
|
wSpread = (wpnData.fSpreadValue / 2.0)
|
|
dir = GGSM_GET_VECTOR_FROM_HEADING(fBaseAngle)
|
|
shotPos = gunpos
|
|
IF (ent.iWeaponShotCounter % 3 = 2)
|
|
shotPos.x -= dir.y * wSpread
|
|
shotPos.y -= dir.x * wSpread
|
|
ELIF (ent.iWeaponShotCounter % 3 = 0)
|
|
shotPos.x += dir.y * wSpread
|
|
shotPos.y += dir.x * wSpread
|
|
ENDIF
|
|
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[ind], wpnData.eProjectileType, shotPos, fBaseAngle, bIsAllied)
|
|
ent.iWeaponShotCounter ++
|
|
bBurstDone = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_SPREAD_DUALARCH
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, 2, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
IF (cnt = 2)
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[0]], wpnData.eProjectileType, gunpos, fBaseAngle, bIsAllied)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sProjectiles[iProjList[0]].eFlags, GGSM_PROJECTILE_BIT_IS_SINEWAVE)
|
|
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[1]], wpnData.eProjectileType, gunpos, fBaseAngle, bIsAllied)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sProjectiles[iProjList[1]].eFlags, GGSM_PROJECTILE_BIT_IS_SINEWAVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sProjectiles[iProjList[1]].eFlags, GGSM_PROJECTILE_BIT_IS_NEG_SINEWAVE)
|
|
bBurstDone = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_SPREAD_BACKVULCAN
|
|
cnt = GGSM_GET_FREE_PROJECTILES(sGGSMData.sProjectiles, 3, iProjList, sGGSMData.iProjectileSearchIndex)
|
|
wSpread = (wpnData.fSpreadValue / 2.0)
|
|
dir = GGSM_GET_VECTOR_FROM_HEADING(fBaseAngle)
|
|
|
|
IF (cnt = 3)
|
|
shotPos = gunpos
|
|
shotPos.x -= dir.y * wSpread
|
|
shotPos.y -= dir.x * wSpread
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[0]], wpnData.eProjectileType, shotPos, fBaseAngle - 180.0, bIsAllied)
|
|
|
|
shotPos = gunpos
|
|
shotPos.x += dir.y * wSpread
|
|
shotPos.y += dir.x * wSpread
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[1]], wpnData.eProjectileType, shotPos, fBaseAngle - 180.0, bIsAllied)
|
|
|
|
|
|
GGSM_PROJECTILE_INIT(sGGSMData.sProjectiles[iProjList[2]], wpnData.eProjectileType, gunpos, fBaseAngle, bIsAllied)
|
|
bBurstDone = TRUE
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
IF (bBurstDone = TRUE)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_BURST_FIRED)
|
|
ent.iWeaponBurstCounter ++
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_FIRED)
|
|
|
|
GGSM_PROJECTILE_DATA projData = GGSM_PROJECTILE_DATA_GET(wpnData.eProjectileType)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(projData.eProjSound, gunpos)
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_UPDATE_WEAPON(GGSM_ENTITY &ent)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_BURST_FIRED)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_BURST_RELOAD_THIS_FRAME)
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_ENTERED_PLAYFIELD)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_ON_SCREEN)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF GGSM_IS_DIALOG_ACTIVE()
|
|
EXIT
|
|
ENDIF
|
|
|
|
// handle slow down
|
|
GGSM_PROJECTILE_DATA projdata
|
|
GGSM_WEAPON_DATA wpnData = GGSM_WEAPON_DATA_GET(ent.eWeaponType)
|
|
|
|
FLOAT fDelta = GET_FRAME_TIME()
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
IF (bIsAllied)
|
|
ent.fWeaponTimer += fDelta
|
|
ELSE
|
|
ent.fWeaponTimer += (fDelta * sGGSMData.fTimeScale)
|
|
ENDIF
|
|
|
|
// update state
|
|
SWITCH (ent.eWeaponState)
|
|
CASE GGSM_WEAPON_STATE_READY
|
|
|
|
projdata = GGSM_PROJECTILE_DATA_GET(wpnData.eProjectileType)
|
|
IF (ent.fWeaponTimer >= projdata.fShotReloadTime)
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_FIRING)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_WEAPON_STATE_FIRING
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_FIRE_WEAPON(ent)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_WEAPON_STATE_FIRED
|
|
IF (wpnData.iNumBursts <= 0) OR (ent.iWeaponBurstCounter < wpnData.iNumBursts)
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_RELOAD)
|
|
ELSE
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_BURST_RELOAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_BURST_RELOAD_THIS_FRAME)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_WEAPON_STATE_RELOAD
|
|
projdata = GGSM_PROJECTILE_DATA_GET(wpnData.eProjectileType)
|
|
IF (ent.fWeaponTimer >= projdata.fShotReloadTime)
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_FIRING)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_WEAPON_STATE_BURST_RELOAD
|
|
IF (ent.fWeaponTimer >= wpnData.fBurstReloadTime)
|
|
ent.iWeaponBurstCounter = 0
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_SPINUP)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_WEAPON_STATE_SPINUP
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_FIRING)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY MOVEMENT FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_STATE(GGSM_ENTITY &ent, GGSM_MOVESTATE_TYPE st)
|
|
ent.eMoveState = st
|
|
ent.fMoveTimer = 0.0
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ENTITY_SET_MOVEMENT_STATE - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(ent.eType), " ARRAY INDEX:", GGSM_ENTITY_GET_ARRAY_INDEX(ent), " MOVETYPE:", GGSM_MOVEMENT_TYPE_TO_STRING(ent.eMoveType), " STATE:", GGSM_MOVESTATE_TYPE_TO_STRING(st))
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(GGSM_ENTITY &ent, VECTOR_2D localTgtPos)
|
|
|
|
ent.iPackedLocalTargetPosition = GGSM_PACK_VECTOR_2D_TO_INT(localTgtPos)
|
|
ent.vLocalDirection = SUBTRACT_VECTOR_2D(localTgtPos, ent.sLocal.vPosition)
|
|
ent.vLocalDirection = NORMALISE_VECTOR_2D(ent.vLocalDirection)
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED_THIS_FRAME)
|
|
|
|
IF GGSM_IS_POINT_BEHIND_PLANE(localTgtPos, ent.vLocalDirection, ent.sLocal.vPosition)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_LAST_PLANE_SIDE)
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_LAST_PLANE_SIDE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(GGSM_ENTITY &ent, VECTOR_2D vWorldPos)
|
|
VECTOR_2D localTgtPos = vWorldPos
|
|
INT iParentIndex = GGSM_ENTITY_GET_PARENT_INDEX(ent)
|
|
|
|
// convert world position into target space
|
|
IF (iParentIndex != GGSM_INVALID_ENTITY)
|
|
localTgtPos = GGSM_TRANSFORM_WORLD_POS_TO_LOCAL_POS(sGGSMData.sEntities[iParentIndex].sWorld, vWorldPos)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, localTgtPos)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Sets the movement type
|
|
/// PARAMS:
|
|
/// ent - entity to set
|
|
/// eType - movement
|
|
/// fMParam1 - param 1
|
|
/// fMparam2 - param 2
|
|
/// NOTE: For different movetypes the params are different
|
|
/// GGSM_MOVEMENT_BG_ATTACK - mParam1 = how to move before scaling in (default is 800.0)
|
|
/// GGSM_MOVEMENT_FORWARD_THEN_BACK - mParam1 = how far to move forward
|
|
/// GGSM_MOVEMENT_ORBIT - mParam1 = dist from center, mParam2 = start angle, mParam3 = revs / sec
|
|
/// GGSM_MOVEMENT_SINWAVE - mParam1 = period length (dist of 1 wave), mParam2 = height of wave
|
|
/// GGSM_MOVEMENT_TARGETTED_WANDER - mParam1 = how long to wait at target,
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_TYPE(GGSM_ENTITY &ent, GGSM_MOVEMENT_TYPE eType, FLOAT fMParam1 = 0.0, FLOAT fMparam2 = 0.0, FLOAT fMparam3 = 0.0)
|
|
ent.eMoveType = eType
|
|
ent.eMoveState = GGSM_MOVESTATE_START
|
|
ent.fMoveParam[0] = fMParam1
|
|
ent.fMoveParam[1] = fMParam2
|
|
ent.fMoveParam[2] = fMParam3
|
|
ent.eMoveFlags = GGSM_MOVE_BIT_NONE
|
|
ent.fMoveTimer = 0.0
|
|
|
|
// do setups based on type
|
|
SWITCH (eType)
|
|
CASE GGSM_MOVEMENT_BG_ATTACK
|
|
IF (ent.fMoveParam[0] = 0.0)
|
|
ent.fMoveParam[0] = 950.0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_FORWARD_THEN_BACK
|
|
IF (ent.fMoveParam[0] = 0.0)
|
|
ent.fMoveParam[0] = 700.0
|
|
ENDIF
|
|
BREAK
|
|
CASE GGSM_MOVEMENT_SIN_WAVE
|
|
ent.iPackedLocalOrigin = GGSM_PACK_VECTOR_2D_TO_INT(ent.sLocal.vPosition)
|
|
BREAK
|
|
CASE GGSM_MOVEMENT_SNAKE_SECTION
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_POSITION_OVERRIDE)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_ORBIT(GGSM_ENTITY &ent, FLOAT fRange, FLOAT fStartAngle = 0.0, FLOAT fRevsPerSec = 1.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_ORBIT, fRange, fStartAngle, fRevsPerSec)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_RETURN_TO_ORIGIN(GGSM_ENTITY &ent)
|
|
VECTOR_2D tmp = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalOrigin)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_MOVE_TO_VECTOR)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, tmp)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_TO_LOCAL_VECTOR(GGSM_ENTITY &ent, VECTOR_2D vec, FLOAT fDelay = 0.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_MOVE_TO_VECTOR, fDelay)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, vec)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(GGSM_ENTITY &ent, VECTOR_2D vec, FLOAT fDelay = 0.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_MOVE_TO_VECTOR, fDelay)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, vec)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_TO_FACE_LOCAL_VECTOR(GGSM_ENTITY &ent, VECTOR_2D vec, FLOAT fDelay = 0.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_ROTATE_TO_FACE_VECTOR, fDelay)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, vec)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_MOVEMENT_TO_FACE_VECTOR(GGSM_ENTITY &ent, VECTOR_2D vec, FLOAT fDelay = 0.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_ROTATE_TO_FACE_VECTOR, fDelay)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, vec)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_LOCAL_TRANSFORM(GGSM_ENTITY &ent, FLOAT x, FLOAT y, FLOAT rot)
|
|
ent.sLocal.vPosition.x = x
|
|
ent.sLocal.vPosition.y = y
|
|
ent.sLocal.fRotation = rot
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(GGSM_ENTITY &ent, FLOAT spd, BOOL bMultByFrameTime = FALSE)
|
|
BOOL bCurCheck
|
|
VECTOR_2D dir
|
|
VECTOR_2D localTgtPos = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalTargetPosition)
|
|
FLOAT fAngle
|
|
|
|
IF (bMultByFrameTime)
|
|
spd = 0 +@ spd
|
|
ENDIF
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += (ent.vLocalDirection.x * spd)
|
|
ent.sLocal.vPosition.y += (ent.vLocalDirection.y * spd)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_ROTATE_TO_FACE_DIRECTION)
|
|
dir = SUBTRACT_VECTOR_2D(localTgtPos, ent.sLocal.vPosition)
|
|
fAngle = GET_HEADING_FROM_VECTOR_2D(dir.x, dir.y) - ent.sLocal.fRotation
|
|
IF (fAngle > 180.0)
|
|
fAngle -= 360.0
|
|
ENDIF
|
|
|
|
IF (fAngle < -180.0)
|
|
fAngle += 360.0
|
|
ENDIF
|
|
|
|
ent.sLocal.fRotation += (0 +@ fAngle)
|
|
ENDIF
|
|
|
|
// we've crossed the plane
|
|
bCurCheck = GGSM_IS_POINT_BEHIND_PLANE(localTgtPos, ent.vLocalDirection, ent.sLocal.vPosition)
|
|
IF (bCurCheck != IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_LAST_PLANE_SIDE)) OR (VECTOR_2D_DIST2(localTgtPos, ent.sLocal.vPosition) <= 1)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED_THIS_FRAME)
|
|
|
|
ent.sLocal.vPosition = localTgtPos
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRE_ON_ARRIVE)
|
|
GGSM_ENTITY_FIRE_WEAPON(ent)
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (bCurCheck)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_LAST_PLANE_SIDE)
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_LAST_PLANE_SIDE)
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET_SCALER(GGSM_ENTITY &ent, FLOAT spd, FLOAT fScaleDist = 400.0, BOOL bMultByFrameTime = FALSE, BOOL bScaleOut = FALSE)
|
|
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, bMultByFrameTime)
|
|
ent.sLocal.vScale = INIT_VECTOR_2D(1.0, 1.0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
VECTOR_2D localTgtPos = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalTargetPosition)
|
|
FLOAT fDist = VECTOR_2D_DIST(localTgtPos, ent.sLocal.vPosition)
|
|
FLOAT fScale = ((fScaleDist - fDist) / fScaleDist)
|
|
fScale = CLAMP(fScale, 0.25, 1.0)
|
|
ent.sLocal.vScale = INIT_VECTOR_2D(fScale, fScale)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
UNUSED_PARAMETER(bScaleOut)
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_PRE_CALCULATE_FOR_ARC(GGSM_ENTITY &ent, VECTOR_2D arcCenter)
|
|
VECTOR_2D temp, tgtPos
|
|
|
|
// work out position to target to
|
|
temp = ent.sLocal.vPosition
|
|
temp.x += ent.vLocalDirection.x * 3000.0
|
|
temp.y += ent.vLocalDirection.y * 3000.0
|
|
|
|
tgtPos = GGSM_GET_CLOSEST_POINT_ON_LINE(arcCenter, ent.sLocal.vPosition, temp, FALSE)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, tgtpos)
|
|
|
|
// work out radius of arc
|
|
temp = SUBTRACT_VECTOR_2D(tgtpos, arcCenter)
|
|
ent.fMoveParam[0] = VECTOR_2D_DIST(tgtPos, arcCenter)
|
|
|
|
// work out first angle point of arc
|
|
ent.fMoveParam[1] = GET_HEADING_FROM_VECTOR_2D(ent.vLocalDirection.x, ent.vLocalDirection.y)
|
|
|
|
// work out angular speed of arc
|
|
ent.fMoveParam[2] = (GGSM_ENTITY_GET_SPEED(ent) / (2.0 * GGSM_PI * ent.fMoveParam[0]))
|
|
|
|
SWITCH (ent.eMoveType)
|
|
CASE GGSM_MOVEMENT_ARC_BASE_LEFT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_BASE_LEFT
|
|
ent.fMoveParam[1] += 90.0
|
|
ent.fMoveParam[2] *= 1.0
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ARC_TOP_LEFT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_TOP_LEFT
|
|
ent.fMoveParam[1] -= 90.0
|
|
ent.fMoveParam[2] *= -1.0
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ARC_TOP_RIGHT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_TOP_RIGHT
|
|
ent.fMoveParam[1] += 90.0
|
|
ent.fMoveParam[2] *= 1.0
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ARC_BASE_RIGHT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_BASE_RIGHT
|
|
ent.fMoveParam[1] -= 90.0
|
|
ent.fMoveParam[2] *= -1.0
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_ARC(GGSM_ENTITY &ent)
|
|
FLOAT fDelta
|
|
FLOAT spd = GGSM_ENTITY_GET_SPEED(ent)
|
|
VECTOR_2D arcCenter = INIT_VECTOR_2D(cfBASE_SCREEN_HALF_WIDTH, cfBASE_SCREEN_HALF_HEIGHT)
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
arcCenter = INIT_VECTOR_2D(cfBASE_SCREEN_HALF_WIDTH, cfBASE_SCREEN_HALF_HEIGHT)
|
|
GGSM_ENTITY_PRE_CALCULATE_FOR_ARC(ent, arcCenter)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_STARTPOS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_STARTPOS
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ARC)
|
|
ent.fDistTravelled = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ARC
|
|
fDelta = (0 +@ (ent.fMoveParam[2] * 360.0 * sGGSMData.fTimeScale))
|
|
ent.fMoveParam[1] += fDelta
|
|
ent.fDistTravelled += ABSF(fDelta)
|
|
|
|
// rotate round arc center
|
|
ent.sLocal.vPosition.x = SIN(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
ent.sLocal.vPosition.y = COS(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
|
|
// add arc center to local to put it back
|
|
ent.sLocal.vPosition.x += arcCenter.x
|
|
ent.sLocal.vPosition.y += arcCenter.y
|
|
|
|
IF (ent.fDistTravelled >= 360.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_ATTACK_KAMAKAZE(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
FLOAT fDist = 600.0
|
|
VECTOR_2D tgtpos = GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
ent.fDistTravelled = 0.0
|
|
ent.iWeaponBurstCounter = 0
|
|
ent.fWeaponTimer = 0
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_WEAPON_STATE(ent, GGSM_WEAPON_STATE_READY)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ (GGSM_ENTITY_GET_SPEED(ent) / 2.0)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
|
|
IF (ent.fDistTravelled > fDist)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_FIRE_WEAPON(ent)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ATTACK)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ATTACK
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_ENTITY_BIT_WPN_BURST_FIRED)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(ent)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, tgtpos)
|
|
IF (ent.eType = GGSM_ENTITY_BANANARED_ATTACK)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_FLYBY_KAMIKAZE, ent.sWorld.vPosition)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 1)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_RAMMING)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_RAMMING
|
|
spd = GGSM_ENTITY_GET_SPEED(ent) * 2.0
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_COMPLETE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_BG_ATTACK(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
VECTOR_2D tgtPos
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
ent.fDistTravelled = 0
|
|
tgtPos.x = ent.sLocal.vPosition.x + (ent.vLocalDirection.x * ent.fMoveParam[0])
|
|
tgtPos.y = ent.sLocal.vPosition.y + (ent.vLocalDirection.y * ent.fMoveParam[0])
|
|
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, tgtPos)
|
|
|
|
ent.sLocal.vScale = INIT_VECTOR_2D(0.5, 0.5)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
spd = (GGSM_ENTITY_GET_SPEED(ent) * 0.75)
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET_SCALER(ent, spd, ent.fMoveParam[0] / 2.0, TRUE)
|
|
IF (ent.eType = GGSM_ENTITY_BANANARED_ATTACK)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_FLYBY_KAMIKAZE, ent.sWorld.vPosition)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 1)
|
|
ELSE
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_FLYBY_UFO, ent.sWorld.vPosition)
|
|
ENDIF
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_NO_COLLISION)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, GGSM_GET_TARGET_AT_PLAYER_POSITION())
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += (ent.vLocalDirection.x * spd)
|
|
ent.sLocal.vPosition.y += (ent.vLocalDirection.y * spd)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_DESTRUCT_ON_IMPACT(GGSM_ENTITY &ent)
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_SELF_DESTRUCT)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_COMPLETE
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_FOLLOW_PATH(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
GGSM_PATH_DATA dat
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
ent.fPathValue = 0
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_SELECT_POS
|
|
dat = GGSM_PATH_DATA_GET(ent.iPathNumber)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, GGSM_PATH_DATA_GET_POINT(dat, FLOOR(ent.fPathValue)))
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
spd = GGSM_ENTITY_GET_SPEED(ent)
|
|
IF NOT GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
ent.fPathValue ++
|
|
dat = GGSM_PATH_DATA_GET(ent.iPathNumber)
|
|
IF (ent.fPathValue >= GGSM_PATH_DATA_GET_NUM_POINTS(dat))
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_FOLLOW_REL_PATH(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
GGSM_PATH_DATA dat
|
|
VECTOR_2D vBasePos, vRootPoint, vRel
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
ent.fPathValue = 0
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_SELECT_POS
|
|
dat = GGSM_PATH_DATA_GET(ent.iPathNumber)
|
|
vBasePos = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalOrigin)
|
|
vRootPoint = GGSM_PATH_DATA_GET_POINT(dat, 0)
|
|
vRel = SUBTRACT_VECTOR_2D(GGSM_PATH_DATA_GET_POINT(dat, FLOOR(ent.fPathValue)), vRootPoint)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_FLIP_RELATIVE_PATH_X)
|
|
vRel.x *= -1.0
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_FLIP_RELATIVE_PATH_Y)
|
|
vRel.y *= -1.0
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, ADD_VECTOR_2D(vBasePos, vRel))
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
spd = GGSM_ENTITY_GET_SPEED(ent)
|
|
IF NOT GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
ent.fPathValue ++
|
|
dat = GGSM_PATH_DATA_GET(ent.iPathNumber)
|
|
IF (ent.fPathValue >= GGSM_PATH_DATA_GET_NUM_POINTS(dat))
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_FORWARD_THEN_BACK(GGSM_ENTITY &ent)
|
|
VECTOR_2D tgtPos
|
|
FLOAT spd
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
tgtPos = ent.sLocal.vPosition
|
|
tgtPos.x += (ent.vLocalDirection.x * ent.fMoveParam[0])
|
|
tgtPos.y += (ent.vLocalDirection.y * ent.fMoveParam[0])
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, tgtpos)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_STARTPOS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_STARTPOS
|
|
spd = GGSM_ENTITY_GET_SPEED(ent)
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
GGSM_ENTITY_FIRE_WEAPON(ent)
|
|
ent.vLocalDirection.x *= -1.0
|
|
ent.vLocalDirection.y *= -1.0
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_ON_SCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_HALF_ARC(GGSM_ENTITY &ent)
|
|
FLOAT fDelta
|
|
FLOAT spd = GGSM_ENTITY_GET_SPEED(ent)
|
|
VECTOR_2D arcCenter
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
arcCenter = INIT_VECTOR_2D(cfBASE_SCREEN_HALF_WIDTH, cfBASE_SCREEN_HALF_HEIGHT)
|
|
GGSM_ENTITY_PRE_CALCULATE_FOR_ARC(ent, arcCenter)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_STARTPOS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_STARTPOS
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ARC)
|
|
ent.fDistTravelled = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ARC
|
|
fDelta = (0 +@ (ent.fMoveParam[2] * 360.0 * sGGSMData.fTimeScale))
|
|
ent.fMoveParam[1] += fDelta
|
|
ent.fDistTravelled += ABSF(fDelta)
|
|
|
|
// rotate round arc center
|
|
ent.sLocal.vPosition.x = SIN(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
ent.sLocal.vPosition.y = COS(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
|
|
// add arc center to local to put it back
|
|
ent.sLocal.vPosition.x += arcCenter.x
|
|
ent.sLocal.vPosition.y += arcCenter.y
|
|
|
|
IF (ent.fDistTravelled >= 180.0)
|
|
ent.vLocalDirection.x *= -1.0
|
|
ent.vLocalDirection.y *= -1.0
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_KAMAKAZE(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
FLOAT fDist = 600.0
|
|
VECTOR_2D tgtpos = GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
ent.fDistTravelled = 0.0
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
|
|
IF (VECTOR_2D_DIST2(tgtpos, ent.sWorld.vPosition) < (fDist * fDist))
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(ent)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, tgtpos)
|
|
IF (ent.eType = GGSM_ENTITY_BANANARED_ATTACK)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_FLYBY_KAMIKAZE, ent.sWorld.vPosition)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 1)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_RAMMING)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_RAMMING
|
|
spd = GGSM_ENTITY_GET_SPEED(ent) * 2.0
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, spd, TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_COMPLETE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_ORBIT(GGSM_ENTITY &ent)
|
|
VECTOR_2D tmp
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
ent.eMoveState = GGSM_MOVESTATE_ACTIVE
|
|
tmp.x = SIN(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
tmp.y = COS(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, tmp)
|
|
|
|
IF (VECTOR_2D_DIST(ADD_VECTOR_2D(tmp, ent.sLocal.vPosition), ent.sLocal.vPosition) < 2)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_STARTPOS)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_STARTPOS
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
// fMoveParam0 is the distance from center
|
|
// fMoveParam1 is the angle around the center
|
|
// fMoveParam2 is revolutions per second
|
|
ent.fMoveParam[1] += (0 +@ (ent.fMoveParam[2] * 360.0 * sGGSMData.fTimeScale))
|
|
ent.sLocal.vPosition.x = SIN(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
ent.sLocal.vPosition.y = COS(ent.fMoveParam[1]) * ent.fMoveParam[0]
|
|
ent.vLocalDirection = NORMALISE_VECTOR_2D(ent.sLocal.vPosition)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_ROTATE_TO_FACE_DIRECTION)
|
|
ent.sLocal.fRotation = GET_HEADING_FROM_VECTOR_2D(ent.sLocal.vPosition.x, ent.sLocal.vPosition.y) - ent.sLocal.fRotation
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_TO_VECTOR(GGSM_ENTITY &ent)
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
IF (ent.fMoveTimer >= ent.fMoveParam[0])
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_WPN_FIRE_ON_ARRIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ATTACK)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ATTACK
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_ENTITY_BIT_WPN_BURST_FIRED)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_ROTATE_FACE_TO_VECTOR(GGSM_ENTITY &ent)
|
|
VECTOR_2D dir
|
|
FLOAT fAngle
|
|
VECTOR_2D localTgtPos = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalTargetPosition)
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
IF (ent.fMoveTimer >= ent.fMoveParam[0])
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
dir = SUBTRACT_VECTOR_2D(localTgtPos, ent.sLocal.vPosition)
|
|
fAngle = GET_HEADING_FROM_VECTOR_2D(dir.x, dir.y) - ent.sLocal.fRotation
|
|
IF (fAngle > 180.0)
|
|
fAngle -= 360.0
|
|
ENDIF
|
|
|
|
IF (fAngle < -180.0)
|
|
fAngle += 360.0
|
|
ENDIF
|
|
|
|
ent.sLocal.fRotation += (0 +@ fAngle)
|
|
|
|
IF (ABSF(fAngle) < 1.0)
|
|
ent.sLocal.fRotation = GET_HEADING_FROM_VECTOR_2D(dir.x, dir.y)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Player controlled entity.
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_ENTITY_MOVE_PLAYER_CONTROLLED(GGSM_ENTITY &ent)
|
|
FLOAT spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
FLOAT hw, hh
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
VECTOR_2D sprsize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D oldPos = ent.sLocal.vPosition
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.eStageFlags, GGSM_STAGE_BIT_STAGE_STARTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_STAGE_STARTED)
|
|
ENDIF
|
|
|
|
ent.sLocal.vPosition.x = 200.0
|
|
ent.sLocal.vPosition.y = 540.0
|
|
ent.vLocalDirection.x = 1.0
|
|
ent.vLocalDirection.y = 0.0
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_PLYR_INVUNERABLE)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 0)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_PLYR_INVUNERABLE // move straight until at ready posF
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 0)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INITIAL_INV_TIME
|
|
ent.sLocal.vPosition.x += (spd / 2.0)
|
|
IF (ent.sLocal.vPosition.x > 600.0)
|
|
ent.sLocal.vPosition.x = 600.0
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_PLYR_DIALOG)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_PLYR_DIALOG
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 0)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INITIAL_INV_TIME
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.eStageFlags, GGSM_STAGE_BIT_INTRO_DONE)
|
|
IF (sGGSMData.sGameStats.level = 1)
|
|
//GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_ASTEROID_ENTER)
|
|
ENDIF
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_INTRO_DONE)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_PLYR_DIALOG_DONE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_PLYR_DIALOG_DONE // move straight until at ready posF
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 0)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INITIAL_INV_TIME
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE // allow player cntrol
|
|
// allow for right stick control.
|
|
IF GGSM_ALTER_POINT_WITH_INPUT(ent.sLocal.vPosition, GGSM_ENTITY_GET_SPEED(ent))
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_MOVE)
|
|
ELIF GGSM_ALTER_POINT_WITH_INPUT(ent.sLocal.vPosition, GGSM_ENTITY_GET_SPEED(ent), GGSM_INPUT_RSTICK)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_MOVE)
|
|
ELIF GGSM_ALTER_POINT_WITH_INPUT(ent.sLocal.vPosition, GGSM_ENTITY_GET_SPEED(ent), GGSM_INPUT_DPAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_MOVE)
|
|
ENDIF
|
|
|
|
// clamp movement
|
|
hw = sprsize.x / 2.0
|
|
hh = sprsize.y / 2.0
|
|
ent.sLocal.vPosition.x = CLAMP(ent.sLocal.vPosition.x, 340.0 + hw, 1590.0 - hw)
|
|
ent.sLocal.vPosition.y = CLAMP(ent.sLocal.vPosition.y, 90.0 + hh, 990.0 - hh)
|
|
|
|
// handle movement anim
|
|
IF (ent.eType = GGSM_ENTITY_PLAYERSHIP)
|
|
IF (ent.sLocal.vPosition.y - oldPos.y < 0)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 1)
|
|
ELIF (ent.sLocal.vPosition.y - oldPos.y > 0)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 2)
|
|
ELSE
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, 0)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (GET_GAME_TIMER() > sGGSMData.iLastMonkeyFireSoundTimeMS)
|
|
IF GGSM_HAS_PLAYER_PRESSED_FIRE()
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.eStageFlags, GGSM_STAGE_BIT_DISABLE_WEAPONS)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_MONKEY_VOICE_FIRE, ent.sWorld.vPosition)
|
|
sGGSMData.iLastMonkeyFireSoundTimeMS = (GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(3000, 6000))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF GGSM_HAS_PLAYER_HOLDING_FIRE()
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_SHOOT)
|
|
ENDIF
|
|
|
|
IF GGSM_HAS_PLAYER_PRESSED_DEFENSE_WEAPON()
|
|
IF (sGGSMData.eWeaponSlot[GGSM_WEAPON_SLOT_DEFENSE] != GGSM_SPRITE_NONE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_DEFENSE_WPN_USED)
|
|
ELSE
|
|
GGSM_PLAY_SOUND(ARCADE_GAMES_SOUND_GGSM_PICKUP_UNAVAILABLE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (ent.fTimer > 1.0)
|
|
IF GGSM_SHOULD_SHOW_TUTORIAL(GGSM_HELP_BIT_MOVE)
|
|
ARCADE_GAMES_HELP_TEXT_PRINT(ARCADE_GAMES_HELP_TEXT_ENUM_GGSM_MOVESHIP)
|
|
ENDIF
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_MOVE)
|
|
ENDIF
|
|
|
|
IF (ent.fTimer > 4.0)
|
|
IF GGSM_SHOULD_SHOW_TUTORIAL(GGSM_HELP_BIT_SHOOT)
|
|
ARCADE_GAMES_HELP_TEXT_CLEAR()
|
|
ARCADE_GAMES_HELP_TEXT_PRINT(ARCADE_GAMES_HELP_TEXT_ENUM_GGSM_FIREWEAPONS)
|
|
ENDIF
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eHelpFlags, GGSM_HELP_BIT_SHOOT)
|
|
ENDIF
|
|
|
|
IF GGSM_HAS_PLAYER_PRESSED_SPECIAL_WEAPON()
|
|
IF (sGGSMData.eWeaponSlot[GGSM_WEAPON_SLOT_SPECIAL] != GGSM_SPRITE_NONE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_SPECIAL_WPN_USED)
|
|
ELSE
|
|
GGSM_PLAY_SOUND(ARCADE_GAMES_SOUND_GGSM_PICKUP_UNAVAILABLE)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Player controlled entity.
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_ENTITY_MOVE_RANDOM_WANDER(GGSM_ENTITY &ent)
|
|
VECTOR_2D tmp
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
ent.eMoveState = GGSM_MOVESTATE_SELECT_POS
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_SELECT_POS
|
|
IF (ent.fMoveTimer >= ent.fMoveParam[0])
|
|
tmp.x = GET_RANDOM_FLOAT_IN_RANGE(GGSM_PX_OVERSCAN_MIN_X + 100, GGSM_PX_OVERSCAN_MAX_X - 100)
|
|
tmp.y = GET_RANDOM_FLOAT_IN_RANGE(GGSM_PX_OVERSCAN_MIN_Y + 100, GGSM_PX_OVERSCAN_MAX_Y - 100)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, tmp)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_FORCE_MOVEMENT_TO_END)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_TO_ORIGIN_ON_MOVE_ABORT)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalOrigin))
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_ORIGIN)
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_ORIGIN
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_SINWAVE(GGSM_ENTITY &ent)
|
|
FLOAT fPeriod
|
|
FLOAT spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
ent.iPackedLocalOrigin = GGSM_PACK_VECTOR_2D_TO_INT(ent.sLocal.vPosition)
|
|
ent.fDistTravelled = 0.0
|
|
|
|
// move param 0 is the period length - movement needed to 1 wave
|
|
IF (ent.fMoveParam[0] = 0.0)
|
|
ent.fMoveParam[0] = 600.0
|
|
ENDIF
|
|
|
|
// move param 1 is the height of the wave
|
|
IF (ent.fMoveParam[1] = 0.0)
|
|
ent.fMoveParam[1] = 88.0
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
ent.fDistTravelled += spd
|
|
|
|
// move forward
|
|
ent.sLocal.vPosition = GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalOrigin)
|
|
ent.sLocal.vPosition.x += (ent.vLocalDirection.x * ent.fDistTravelled)
|
|
ent.sLocal.vPosition.y += (ent.vLocalDirection.y * ent.fDistTravelled)
|
|
|
|
// horizontal displacement - get the perpendicular
|
|
fPeriod = TO_FLOAT(FLOOR(ent.fDistTravelled) % FLOOR(ent.fMoveParam[0])) / ent.fMoveParam[0]
|
|
spd = SIN(fPeriod * 360.0) * ent.fMoveParam[1]
|
|
ent.sLocal.vPosition.x += (ent.vLocalDirection.y * spd)
|
|
ent.sLocal.vPosition.y += (ent.vLocalDirection.x * spd)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_SNAKESECTION(GGSM_ENTITY &ent)
|
|
VECTOR_2D dir
|
|
VECTOR_2D parentPos
|
|
VECTOR_2D desiredPos
|
|
INT iParent = GGSM_ENTITY_GET_PARENT_INDEX(ent)
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_POSITION_OVERRIDE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
IF (iParent = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_POSITION_OVERRIDE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
parentPos = sGGSMData.sEntities[iParent].sWorld.vPosition
|
|
|
|
dir.x = parentPos.x - ent.sWorld.vPosition.x
|
|
dir.y = parentPos.y - ent.sWorld.vPosition.y
|
|
ent.vLocalDirection = NORMALISE_VECTOR_2D(dir)
|
|
|
|
desiredPos.x = parentPos.x - (ent.sLocal.vPosition.x * ent.vLocalDirection.x)
|
|
desiredPos.y = parentPos.y - (ent.sLocal.vPosition.x * ent.vLocalDirection.y)
|
|
ent.sWorld.vPosition = LERP_VECTOR_2D(ent.sWorld.vPosition, desiredPos, 0.5)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_ROTATE_TO_FACE_DIRECTION)
|
|
ent.sWorld.fRotation = GET_HEADING_FROM_VECTOR_2D(ent.vLocalDirection.x, ent.vLocalDirection.y)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Simple Movestraight function
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// RETURNS:
|
|
/// Returns true when entity has left the play field
|
|
PROC GGSM_ENTITY_MOVE_STRAIGHT(GGSM_ENTITY &ent)
|
|
FLOAT spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
|
|
IF (ent.eMoveState = GGSM_MOVESTATE_START)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Player controlled entity.
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_ENTITY_MOVE_TARGETTED_WANDER(GGSM_ENTITY &ent)
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_SELECT_POS
|
|
IF (ent.fMoveTimer >= ent.fMoveParam[0])
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, GGSM_GET_TARGET_AT_PLAYER_POSITION())
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_FORCE_MOVEMENT_TO_END)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_TO_ORIGIN_ON_MOVE_ABORT)
|
|
GGSM_ENTITY_SET_TARGET_LOCAL_VECTOR(ent, GGSM_UNPACK_VECTOR_2D(ent.iPackedLocalOrigin))
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_ORIGIN)
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_ORIGIN
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_COMPLETE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_MIDDLE_Y_RANGE(GGSM_ENTITY &ent)
|
|
VECTOR_2D tgtPos
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, INIT_VECTOR_2D(1225.0, 540.0))
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_SELECT_POS
|
|
tgtPos = ent.sWorld.vPosition
|
|
tgtPos.y = GET_RANDOM_FLOAT_IN_RANGE(370.0, 762.0)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, tgtPos)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_SELECT_POS)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_MOVE_TRACK_PLAYER_Y(GGSM_ENTITY &ent)
|
|
FLOAT spd
|
|
VECTOR_2D tgtPos = GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
|
|
SWITCH (ent.eMoveState)
|
|
CASE GGSM_MOVESTATE_START // start
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_GOTO_POS)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(ent, INIT_VECTOR_2D(1225.0, 540.0))
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_GOTO_POS
|
|
IF GGSM_ENTITY_UPDATE_MOVEMENT_TO_TARGET(ent, GGSM_ENTITY_GET_SPEED(ent), TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_STATE(ent, GGSM_MOVESTATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_MOVESTATE_ACTIVE
|
|
spd = 0 +@ GGSM_ENTITY_GET_SPEED(ent)
|
|
ent.fDistTravelled += spd
|
|
ent.sLocal.vPosition.x += ent.vLocalDirection.x * spd
|
|
ent.sLocal.vPosition.y += ent.vLocalDirection.y * spd
|
|
|
|
IF (ABSF(ent.sWorld.vPosition.y - tgtPos.y) > 30.0)
|
|
IF (ent.sWorld.vPosition.y < tgtPos.y)
|
|
ent.vLocalDirection = INIT_VECTOR_2D(0, 1)
|
|
ELSE
|
|
ent.vLocalDirection = INIT_VECTOR_2D(0, -1)
|
|
ENDIF
|
|
ELSE
|
|
ent.vLocalDirection = INIT_VECTOR_2D(0, 0)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// ENTITY FUNCTIONS
|
|
//-------------------------------------------------
|
|
|
|
FUNC BOOL GGSM_ENTITY_IS_AT_FULL_HEALTH(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
RETURN (ent.iHP >= dat.iMaxHP)
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_RESET_HEALTH(GGSM_ENTITY &ent)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
ent.iHP = dat.iMaxHP
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets an Entity to default
|
|
PROC GGSM_ENTITY_RESET(GGSM_ENTITY &ent)
|
|
ent.eType = GGSM_ENTITY_INVALID
|
|
ent.eState = GGSM_ENTITY_STATE_NONE
|
|
ent.eFlags = GGSM_ENTITY_BIT_NONE
|
|
ent.fExplodeTimer = 0.0
|
|
ent.iHP = 0
|
|
ent.eSpriteAnim = GGSM_SPRITE_ANIM_NONE
|
|
ent.fTimer = 0.0
|
|
ent.fAnimFrame = 0.0
|
|
|
|
GGSM_IDENTITY_TRANSFORM(ent.sLocal)
|
|
GGSM_IDENTITY_TRANSFORM(ent.sWorld)
|
|
|
|
GGSM_ENTITY_SET_PARENT_INDEX(ent, GGSM_INVALID_GROUP_ID)
|
|
ent.iGroupID = GGSM_INVALID_GROUP_ID
|
|
ent.eMoveFlags = GGSM_MOVE_BIT_NONE
|
|
ent.iPackedLocalTargetPosition = 0
|
|
GGSM_ENTITY_CLEAR_Z_DEPTH(ent)
|
|
ent.fDistTravelled = 0
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets the entity array
|
|
/// PARAMS:
|
|
/// eType - Type this is used for collison type things
|
|
/// array -
|
|
PROC GGSM_RESET_ENTITY_ARRAY(GGSM_ENTITY &array[])
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
GGSM_ENTITY_RESET(array[i])
|
|
GGSM_ENTITY_SET_ARRAY_INDEX(array[i], i)
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_SET_STATE(GGSM_ENTITY &ent, GGSM_ENTITY_STATE eState)
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ENTITY_SET_STATE - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(ent.eType), " ARRAY INDEX:", GGSM_ENTITY_GET_ARRAY_INDEX(ent), " STATE:", GGSM_ENTITY_STATE_TO_STRING(eState))
|
|
ent.eState = eState
|
|
ent.fTimer = 0
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Destroy Entity
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_ENTITY_DESTROY(GGSM_ENTITY &ent)
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_FORCE_SCROLLING_TO_STOP)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_BRING_CAMERA_TO_STOP)
|
|
ENDIF
|
|
|
|
GGSM_REMOVE_ENTITY_FROM_GROUP(ent)
|
|
GGSM_ENTITY_CLEAR_Z_DEPTH(ent)
|
|
ent.eFlags = GGSM_ENTITY_BIT_NONE
|
|
ent.eState = GGSM_ENTITY_STATE_NONE
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ENTITY_DESTROY - IND:", iArrayIndex, " TYPE: ", GGSM_ENTITY_TYPE_TO_STRING(ent.eType))
|
|
|
|
IF (iArrayIndex = sGGSMData.iPlayerShipIndex)
|
|
sGGSMData.iPlayerShipIndex = GGSM_INVALID_ENTITY
|
|
ENDIF
|
|
|
|
IF (iArrayIndex = sGGSMData.iPlayerDecoyIndex)
|
|
sGGSMData.iPlayerDecoyIndex = GGSM_INVALID_ENTITY
|
|
ENDIF
|
|
|
|
IF (iArrayIndex = sGGSMData.iPlayerShieldIndex)
|
|
sGGSMData.iPlayerShieldIndex = GGSM_INVALID_ENTITY
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_RESET(ent)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_ATTACH_TO_PARENT(GGSM_ENTITY &ent, GGSM_ENTITY &parent, BOOL bJoinParentGroup = TRUE)
|
|
GGSM_ENTITY_SET_PARENT_INDEX(ent, GGSM_ENTITY_GET_ARRAY_INDEX(parent))
|
|
GGSM_TRANSFORM_WORLD_TO_LOCAL(parent.sWorld, ent.sWorld, ent.sLocal)
|
|
|
|
IF (bJoinParentGroup = TRUE)
|
|
IF (parent.iGroupID != GGSM_INVALID_GROUP_ID) AND (parent.iGroupID != ent.iGroupID)
|
|
GGSM_REMOVE_ENTITY_FROM_GROUP(ent)
|
|
GGSM_ADD_ENTITY_TO_GROUP(ent, parent.iGroupID)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
UNUSED_PARAMETER(bJoinParentGroup)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Updates the on screen checks
|
|
/// PARAMS:
|
|
/// ent -
|
|
/// RETURNS:
|
|
/// returns true if the offscreen checks say we should be deleted
|
|
FUNC BOOL GGSM_ENTITY_UPDATE_SCREEN_CHECKS(GGSM_ENTITY &ent)
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
|
|
IF NOT GGSM_IS_COLLIDER_AABB_ON_SCREEN(ent.sCollider)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_ON_SCREEN)
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_ENTERED_PLAYFIELD)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (ent.iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[ent.iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
CLEAR_BIT(sGGSMData.sEntityGroup[ent.iGroupID].iMembersOnStageBitSet, iArrayIndex)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[ent.iGroupID].eFlags, GGSM_GROUP_BIT_END_WHEN_ALL_OFFSCREEN)
|
|
RETURN (sGGSMData.sEntityGroup[ent.iGroupID].iMembersOnStageBitSet = 0)
|
|
ENDIF
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_ON_SCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_ENTERED_PLAYFIELD)
|
|
|
|
IF (ent.iGroupID != GGSM_INVALID_GROUP_ID)
|
|
SET_BIT(sGGSMData.sEntityGroup[ent.iGroupID].iMembersOnStageBitSet, iArrayIndex)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Explode Entity
|
|
/// PARAMS:
|
|
/// ent -
|
|
PROC GGSM_ENTITY_EXPLODE(GGSM_ENTITY &ent)
|
|
IF (ent.eState != GGSM_ENTITY_STATE_ALIVE) AND (ent.eState != GGSM_ENTITY_STATE_UNDEAD)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT n, sc
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
INT iGroupID = GGSM_ENTITY_GET_GROUP_ID(ent)
|
|
INT iParent = GGSM_ENTITY_GET_PARENT_INDEX(ent)
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ENTITY_EXPLODE - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(ent.eType), " ARRAY INDEX:", iArrayIndex)
|
|
ent.fTimer = 0
|
|
|
|
// some enemies shoot when they die
|
|
IF NOT bIsAllied
|
|
IF (ent.eType = GGSM_ENTITY_CHERRYBOMB)
|
|
GGSM_PROJECTILE_CREATE_ENEMY_RADIAL_SPREAD(GGSM_PROJECTILE_ENEMY_SHOT, ent.sWorld.vPosition, GET_RANDOM_INT_IN_RANGE(5, 8), GET_RANDOM_FLOAT_IN_RANGE(0, 360), FALSE)
|
|
ELIF (ent.eType = GGSM_ENTITY_PEANUT_METEOR)
|
|
GGSM_PROJECTILE_CREATE_ENEMY_CONE_SPREAD(GGSM_PROJECTILE_ENEMY_SHOT, ent.sWorld.vPosition, 90.0, 3, TRUE)
|
|
ENDIF
|
|
|
|
IF (sGGSMData.bHardMode)
|
|
GGSM_PROJECTILE_CREATE_ENEMY_RADIAL_SPREAD(GGSM_PROJECTILE_ENEMY_SHOT, ent.sWorld.vPosition, GET_RANDOM_INT_IN_RANGE(1, 6), 0.0, TRUE)
|
|
ENDIF
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_NO_TAKEDOWN_BONUS)
|
|
sGGSMData.iEnemiesDestroyed ++
|
|
sGGSMData.sGameStats.kills ++
|
|
|
|
sGGSMData.fChainMultiplier ++
|
|
IF (sGGSMData.fChainMultiplier > GGSM_CHAIN_MAX)
|
|
sGGSMData.fChainMultiplier = GGSM_CHAIN_MAX
|
|
ENDIF
|
|
|
|
sGGSMData.iKillStreak ++
|
|
sGGSMData.fKillStreakTimer = GGSM_TIME_FOR_KILL_STREAK
|
|
|
|
IF GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
IF (sGGSMData.iKillStreak >= GGSM_KILLS_NEEDED_FOR_KILL_STREAK)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_MONKEY_VOICE_KILL_STREAK, sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].sWorld.vPosition)
|
|
sGGSMData.iKillStreak = 0
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
sGGSMData.iLastEnemyDeathTimeMS = GET_GAME_TIMER()
|
|
|
|
IF (FLOOR(sGGSMData.fChainMultiplier) > 1)
|
|
sc = FLOOR(TO_FLOAT(GGSM_ENTITY_GET_SCORE_FROM_TYPE(ent.eType)) * FLOOR(sGGSMData.fChainMultiplier))
|
|
ELSE
|
|
sc = GGSM_ENTITY_GET_SCORE_FROM_TYPE(ent.eType)
|
|
ENDIF
|
|
GGSM_INCREASE_PLAYER_SCORE(sc)
|
|
ENDIF
|
|
|
|
|
|
// relink sections
|
|
IF (iGroupID != GGSM_INVALID_GROUP_ID) AND (sGGSMData.sEntityGroup[iGroupID].iLeader = iArrayIndex)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
REPEAT GGSM_MAX_ENTITIES n
|
|
IF (n != iArrayIndex) AND (GGSM_ENTITY_GET_GROUP_ID(sGGSMData.sEntities[n]) = iGroupID)
|
|
IF (sGGSMData.sEntities[n].eState = GGSM_ENTITY_STATE_UNDEAD)
|
|
GGSM_ENTITY_SET_STATE(sGGSMData.sEntities[n], GGSM_ENTITY_STATE_ALIVE)
|
|
ENDIF
|
|
GGSM_ENTITY_EXPLODE(sGGSMData.sEntities[n])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
REPEAT GGSM_MAX_ENTITIES n
|
|
IF GGSM_ENTITY_GET_PARENT_INDEX(sGGSMData.sEntities[n]) = iArrayIndex
|
|
GGSM_ENTITY_SET_PARENT_INDEX(sGGSMData.sEntities[n], iParent)
|
|
|
|
IF (iParent = GGSM_INVALID_ENTITY)
|
|
sGGSMData.sEntities[n].sLocal = sGGSMData.sEntities[n].sWorld
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
GGSM_REMOVE_ENTITY_FROM_GROUP(ent)
|
|
|
|
ent.iInvTimeMS = -HIGHEST_INT
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_TOOK_DAMAGE_THIS_FRAME)
|
|
|
|
// if i'm the player
|
|
IF (iArrayIndex = sGGSMData.iPlayerShipIndex)
|
|
sGGSMData.iNoMissBonus = 0
|
|
sGGSMData.iNoDamageBonus = 0
|
|
sGGSMData.fChainMultiplier = 0.0
|
|
sGGSMData.fTimeScale = 1.0
|
|
GGSM_DESTROY_ALL_FACTION_BULLETS(sGGSMData.sProjectiles, TRUE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_DIED)
|
|
SET_CONTROL_SHAKE(FRONTEND_CONTROL, 300, 100)
|
|
IF (sGGSMData.iPlayerLives > 0)
|
|
sGGSMData.iPlayerLives --
|
|
ENDIF
|
|
sGGSMData.bGrazed = FALSE
|
|
IF (sGGSMData.iPlayerLives = 0)
|
|
GGSM_PLAY_AVATAR_GAME_OVER_ANIM()
|
|
ELSE
|
|
GGSM_PLAY_AVATAR_LOST_LIFE_ANIM()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_STATE(ent, GGSM_ENTITY_STATE_EXPLODING)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Damage the entity
|
|
/// PARAMS:
|
|
/// ent - entity to damage
|
|
FUNC BOOL GGSM_ENTITY_DAMAGE(GGSM_ENTITY &ent, INT iDP = 1, BOOL bIgnoreInvunerable = FALSE)
|
|
|
|
IF (GET_GAME_TIMER() < ent.iInvTimeMS) AND (bIgnoreInvunerable = FALSE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (ent.eState != GGSM_ENTITY_STATE_ALIVE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// check to see if damage affects parent (this is for bosses who have multiple bits)
|
|
INT iArrayIndex = GGSM_ENTITY_GET_ARRAY_INDEX(ent)
|
|
INT iGroupID = GGSM_ENTITY_GET_GROUP_ID(ent)
|
|
IF (iGroupID != GGSM_INVALID_GROUP_ID)
|
|
IF (sGGSMData.sEntityGroup[iGroupID].iLeader != GGSM_INVALID_ENTITY)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
GGSM_ENTITY_DAMAGE(sGGSMData.sEntities[sGGSMData.sEntityGroup[iGroupID].iLeader], iDP)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ent.iHP -= iDP
|
|
IF (iArrayIndex = sGGSMData.iPlayerShipIndex)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_DAMAGED)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INV_TIME
|
|
SET_CONTROL_SHAKE(FRONTEND_CONTROL, 100, 100)
|
|
sGGSMData.fChainMultiplier = 0
|
|
sGGSMData.iNoDamageBonus = 0
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_PLAYERSHIELD)
|
|
SET_CONTROL_SHAKE(FRONTEND_CONTROL, 100, 100)
|
|
ENDIF
|
|
|
|
IF (ent.iHP <= 0)
|
|
ent.iHP = 0
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_DIE_ONLY_FROM_EXPLOSIONS)
|
|
GGSM_ENTITY_SET_STATE(ent, GGSM_ENTITY_STATE_FAKE_EXPLODING)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_PLAYERSHIELD)
|
|
GGSM_ENTITY_DESTROY(ent)
|
|
ELSE
|
|
GGSM_ENTITY_EXPLODE(ent)
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(dat.eDamageSound, ent.sWorld.vPosition)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_TOOK_DAMAGE_THIS_FRAME)
|
|
|
|
IF (iArrayIndex = sGGSMData.iPlayerShipIndex)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INV_TIME
|
|
ELIF GGSM_ENTITY_IS_STRONG(ent)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_BOSS_INV_TIME
|
|
ELSE
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_ENTITY_INV_TIME
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Update the projectile array
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// RETURNS:
|
|
/// # of active projectiles
|
|
FUNC INT GGSM_ENTITY_NUKE_ARRAY(GGSM_ENTITY &array[], BOOL bAllied)
|
|
INT i, iDead
|
|
INT cnt = COUNT_OF(array)
|
|
INT dp
|
|
|
|
REPEAT cnt i
|
|
IF (array[i].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = bAllied)
|
|
IF NOT GGSM_ENTITY_IS_STRONG(array[i])
|
|
IF GGSM_ENTITY_DAMAGE(array[i], 30, TRUE)
|
|
iDead ++
|
|
ENDIF
|
|
ELSE
|
|
dp = GGSM_ENTITY_GET_PERCENTAGE_OF_HEALTH(array[i], 30)
|
|
IF GGSM_ENTITY_DAMAGE(array[i], dp, TRUE)
|
|
iDead ++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN iDead
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Update the projectile array
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// RETURNS:
|
|
/// # of active projectiles
|
|
FUNC INT GGSM_ENTITY_DAMAGE_ARRAY(GGSM_ENTITY &array[], BOOL bAllied, INT iDP)
|
|
INT i, iDead
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
REPEAT cnt i
|
|
IF (array[i].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = bAllied)
|
|
IF GGSM_ENTITY_DAMAGE(array[i], iDP, TRUE)
|
|
iDead ++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN iDead
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Update the projectile array
|
|
/// PARAMS:
|
|
/// array - array
|
|
/// RETURNS:
|
|
/// # of active projectiles
|
|
PROC GGSM_ENTITY_EXPLODE_ARRAY(GGSM_ENTITY &array[], BOOL bAllied)
|
|
INT i
|
|
INT cnt = COUNT_OF(array)
|
|
|
|
CPRINTLN(DEBUG_MINIGAME, "GGSM_ENTITY_EXPLODE_ARRAY")
|
|
REPEAT cnt i
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(array[i].eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = bAllied)
|
|
IF (array[i].eState != GGSM_ENTITY_STATE_NONE)
|
|
CPRINTLN(DEBUG_MINIGAME, "GGSM_ENTITY_EXPLODE_ARRAY - TYPE:", GGSM_ENTITY_TYPE_TO_STRING(array[i].eType))
|
|
GGSM_ENTITY_EXPLODE(array[i])
|
|
GGSM_ENTITY_SET_STATE(array[i], GGSM_ENTITY_STATE_EXPLODING)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_UPDATE_MOVEMENT(GGSM_ENTITY &ent)
|
|
SWITCH (ent.eMoveType)
|
|
CASE GGSM_MOVEMENT_ARC_BASE_LEFT
|
|
CASE GGSM_MOVEMENT_ARC_BASE_RIGHT
|
|
CASE GGSM_MOVEMENT_ARC_TOP_LEFT
|
|
CASE GGSM_MOVEMENT_ARC_TOP_RIGHT
|
|
GGSM_ENTITY_MOVE_ARC(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ATTACK_KAMAZAKE
|
|
GGSM_ENTITY_MOVE_ATTACK_KAMAKAZE(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_BG_ATTACK
|
|
GGSM_ENTITY_MOVE_BG_ATTACK(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_DESTRUCT_ON_IMPACT
|
|
GGSM_ENTITY_MOVE_DESTRUCT_ON_IMPACT(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_FOLLOW_PATH
|
|
GGSM_ENTITY_MOVE_FOLLOW_PATH(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_FOLLOW_REL_PATH
|
|
GGSM_ENTITY_MOVE_FOLLOW_REL_PATH(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_FORWARD_THEN_BACK
|
|
GGSM_ENTITY_MOVE_FORWARD_THEN_BACK(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_HALF_ARC_BASE_LEFT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_BASE_RIGHT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_TOP_LEFT
|
|
CASE GGSM_MOVEMENT_HALF_ARC_TOP_RIGHT
|
|
GGSM_ENTITY_MOVE_HALF_ARC(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_KAMAZAKE
|
|
GGSM_ENTITY_MOVE_KAMAKAZE(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_MOVE_TO_VECTOR
|
|
GGSM_ENTITY_MOVE_TO_VECTOR(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ORBIT
|
|
GGSM_ENTITY_MOVE_ORBIT(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_PLAYER_CONTROLLED
|
|
GGSM_ENTITY_MOVE_PLAYER_CONTROLLED(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_RANDOM_WANDER
|
|
GGSM_ENTITY_MOVE_RANDOM_WANDER(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_ROTATE_TO_FACE_VECTOR
|
|
GGSM_ENTITY_MOVE_ROTATE_FACE_TO_VECTOR(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_SIN_WAVE
|
|
GGSM_ENTITY_MOVE_SINWAVE(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_SNAKE_SECTION
|
|
GGSM_ENTITY_MOVE_SNAKESECTION(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_STRAIGHT
|
|
GGSM_ENTITY_MOVE_STRAIGHT(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_TARGETTED_WANDER
|
|
GGSM_ENTITY_MOVE_TARGETTED_WANDER(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_TRACK_PLAYER_Y
|
|
GGSM_ENTITY_MOVE_TRACK_PLAYER_Y(ent)
|
|
BREAK
|
|
|
|
CASE GGSM_MOVEMENT_MIDDLE_Y_RANGE
|
|
GGSM_ENTITY_MOVE_MIDDLE_Y_RANGE(ent)
|
|
BREAK
|
|
/*
|
|
DEFAULT
|
|
CASSERTLN(DEBUG_MINIGAME, "FORGOT TO WRITE THE MOVEMENT FUNCTION - USING DEFAULT - MOVE TYPE:", GGSM_MOVEMENT_TYPE_TO_STRING(ent.eMoveType))
|
|
GGSM_ENTITY_MOVE_STRAIGHT(ent)
|
|
BREAK
|
|
*/
|
|
ENDSWITCH
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_FORCE_SCROLLING_TO_STOP)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_BRING_CAMERA_TO_STOP)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_ENTITY_UPDATE_EXPLOSIONS(GGSM_ENTITY &ent)
|
|
INT ind
|
|
FLOAT fSize
|
|
VECTOR_2D vPos
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
FLOAT spd = 0 +@ (GGSM_ENTITY_GET_SPEED(ent) / 2.0)
|
|
ent.sLocal.vPosition.x += dat.vExplodeVelocity.x * spd
|
|
ent.sLocal.vPosition.y += dat.vExplodeVelocity.y * spd
|
|
|
|
IF bIsAllied
|
|
ent.fExplodeTimer -= GET_FRAME_TIME()
|
|
ELSE
|
|
ent.fExplodeTimer -= (GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_FORCE_SCROLLING_TO_STOP)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_BRING_CAMERA_TO_STOP)
|
|
ENDIF
|
|
|
|
IF (ent.fTimer >= dat.fTotalExplodeTime)
|
|
IF GGSM_GET_FREE_FXSPRITE(sGGSMData.sFXSprite, ind, sGGSMData.iExplosionSearchIndex)
|
|
GGSM_FXSPRITE_INIT_ANIMATED(sGGSMData.sFXSprite[ind], ent.sWorld.vPosition, GGSM_SPRITE_ANIM_EXPLOSION, 2.0)
|
|
GGSM_FXSPRITE_SET_PHYSICAL_RADIUS(sGGSMData.sFXSprite[ind], GGSM_GET_DOMINANT_SPRITE_SIZE(dat.eSpriteType) * 1.5)
|
|
|
|
IF (dat.eDieSound != ARCADE_GAMES_SOUND_END)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(dat.eDieSound, ent.sWorld.vPosition)
|
|
ENDIF
|
|
|
|
IF GGSM_ENTITY_IS_MAIN_BOSS_SECTION(ent)
|
|
GGSM_NUKE_WHITE_INSTANT()
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_DESTROY(ent)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (ent.fExplodeTimer > 0.0)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_FXSPRITE(sGGSMData.sFXSprite, ind, sGGSMData.iExplosionSearchIndex)
|
|
fSize = GGSM_GET_DOMINANT_SPRITE_SIZE(dat.eSpriteType) * GET_RANDOM_FLOAT_IN_RANGE(0.5, 1.0)
|
|
vPos = GGSM_GET_RANDOM_POINT_ON_ENTITY(ent)
|
|
GGSM_FXSPRITE_INIT_ANIMATED(sGGSMData.sFXSprite[ind], vPos, GGSM_SPRITE_ANIM_EXPLOSION, 2.0)
|
|
GGSM_FXSPRITE_SET_PHYSICAL_RADIUS(sGGSMData.sFXSprite[ind], fSize)
|
|
ent.fExplodeTimer = dat.fExplodeDelay
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_ENTITY_UPDATE_FAKE_EXPLOSIONS(GGSM_ENTITY &ent)
|
|
INT ind
|
|
FLOAT fSize
|
|
VECTOR_2D vPos
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
|
|
IF bIsAllied
|
|
ent.fExplodeTimer -= GET_FRAME_TIME()
|
|
ELSE
|
|
ent.fExplodeTimer -= (GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
ENDIF
|
|
|
|
IF (ent.fTimer >= dat.fTotalExplodeTime)
|
|
GGSM_ENTITY_SET_STATE(ent, GGSM_ENTITY_STATE_UNDEAD)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.fExplodeTimer > 0.0)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_FXSPRITE(sGGSMData.sFXSprite, ind, sGGSMData.iExplosionSearchIndex)
|
|
fSize = GGSM_GET_DOMINANT_SPRITE_SIZE(dat.eSpriteType) * GET_RANDOM_FLOAT_IN_RANGE(0.5, 1.0)
|
|
vPos = GGSM_GET_RANDOM_POINT_ON_ENTITY(ent)
|
|
GGSM_FXSPRITE_INIT_ANIMATED(sGGSMData.sFXSprite[ind], vPos, GGSM_SPRITE_ANIM_EXPLOSION, 2.0)
|
|
GGSM_FXSPRITE_SET_PHYSICAL_RADIUS(sGGSMData.sFXSprite[ind], fSize)
|
|
ent.fExplodeTimer = dat.fExplodeDelay
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
FUNC BOOL GGSM_ENTITY_UPDATE(GGSM_ENTITY &ent)
|
|
INT iParent = GGSM_ENTITY_GET_PARENT_INDEX(ent)
|
|
BOOL bIsAllied = IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(ent.eType)
|
|
|
|
// update timer
|
|
sGGSMData.iEntitiesActive ++
|
|
IF bIsAllied
|
|
ent.fTimer += GET_FRAME_TIME()
|
|
ent.fMoveTimer += GET_FRAME_TIME()
|
|
ELSE
|
|
ent.fTimer += (GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
ent.fMoveTimer += (GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_ENEMIES_ACTIVE)
|
|
ENDIF
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED_THIS_FRAME)
|
|
|
|
IF (ent.eState = GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_ENTITY_UPDATE_MOVEMENT(ent)
|
|
ELIF (ent.eState = GGSM_ENTITY_STATE_EXPLODING)
|
|
IF GGSM_ENTITY_UPDATE_EXPLOSIONS(ent)
|
|
GGSM_ENTITY_DESTROY(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELIF (ent.eState = GGSM_ENTITY_STATE_FAKE_EXPLODING)
|
|
GGSM_ENTITY_UPDATE_FAKE_EXPLOSIONS(ent)
|
|
ENDIF
|
|
|
|
// update parenting
|
|
IF (iParent != GGSM_INVALID_ENTITY)
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(ent.eMoveFlags, GGSM_MOVE_BIT_POSITION_OVERRIDE)
|
|
GGSM_TRANSFORM_LOCAL_TO_WORLD(sGGSMData.sEntities[iParent].sWorld, ent.sLocal, ent.sWorld)
|
|
ENDIF
|
|
ELSE
|
|
ent.sWorld = ent.sLocal
|
|
ENDIF
|
|
|
|
IF (ent.eType = GGSM_ENTITY_PLAYERSHIELD) AND GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
ent.sWorld = sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].sWorld
|
|
ENDIF
|
|
|
|
GGSM_COLLIDER_TRANSFORM(ent.sCollider, ent.sWorld, dat.sCollisionData)
|
|
|
|
IF GGSM_ENTITY_UPDATE_SCREEN_CHECKS(ent)
|
|
GGSM_ENTITY_DESTROY(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_TOOK_DAMAGE_THIS_FRAME)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_TOOK_DAMAGE_THIS_FRAME)
|
|
ENDIF
|
|
|
|
// only do the stuff below if we are actually alive
|
|
IF (ent.eState != GGSM_ENTITY_STATE_ALIVE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (ent.eSpriteAnim != GGSM_SPRITE_ANIM_NONE)
|
|
GGSM_SPRITE_UPDATE_ANIMATION(ent.eSpriteAnim, ent.fAnimFrame, NOT bIsAllied)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_UPDATE_WEAPON(ent)
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(ent.eFlags, GGSM_ENTITY_BIT_SELF_DESTRUCT)
|
|
GGSM_ENTITY_EXPLODE(ent)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
// PURPOSE:
|
|
/// Initialize an entity based on data type
|
|
/// PARAMS:
|
|
/// ent - entity to intialize
|
|
/// eType - entity type
|
|
/// vLocalPos - Local Position (for most objects this will be the world position
|
|
/// fLocalRot - Local Rotation
|
|
/// iParentEntity - index into sGGSMData.sEnemyShips for linking boss parts to each other (ONLY USE ON ENEMIES)
|
|
PROC GGSM_ENTITY_INIT(GGSM_ENTITY &ent, GGSM_ENTITY_TYPE eType, VECTOR_2D vLocalPos, FLOAT fLocalRot = 0.0, BOOL bIsFriendly = FALSE, INT iParentEntity = GGSM_INVALID_ENTITY, BOOL bCountTowardsTakedown = TRUE)
|
|
GGSM_ENTITY_RESET(ent)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(eType)
|
|
|
|
ent.eType = eType
|
|
GGSM_ENTITY_RESET_HEALTH(ent)
|
|
ent.eWeaponState = GGSM_WEAPON_STATE_READY
|
|
ent.iPackedColor = GGSM_PACK_RGBA_COLOUR_STRUCT(sGGSMData.rgbaSprite)
|
|
|
|
GGSM_ENTITY_SET_Z_DEPTH(ent, 0)
|
|
GGSM_ENTITY_SET_STATE(ent, GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_ENTITY_SET_WEAPON(ent, GGSM_WEAPON_DEFAULT)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_MOVEMENT_NONE)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(ent, entData.iDefaultAnimFrame)
|
|
|
|
// set initial bits
|
|
IF (bIsFriendly)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED)
|
|
ent.iInvTimeMS = GET_GAME_TIMER() + GGSM_PLAYER_INITIAL_INV_TIME
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_BOSS_INVUNERABLE)
|
|
ENDIF
|
|
|
|
// movement
|
|
ent.sLocal.vPosition = vLocalPos
|
|
ent.sLocal.fRotation = fLocalRot
|
|
ent.iPackedLocalOrigin = GGSM_PACK_VECTOR_2D_TO_INT(vLocalPos)
|
|
ent.fSpeed = entData.fBaseSpeed
|
|
|
|
// parenting
|
|
ent.iGroupID = GGSM_INVALID_GROUP_ID
|
|
GGSM_ENTITY_SET_PARENT_INDEX(ent, iParentEntity)
|
|
IF (iParentEntity != GGSM_INVALID_ENTITY)
|
|
GGSM_TRANSFORM_LOCAL_TO_WORLD(sGGSMData.sEntities[iParentEntity].sWorld, ent.sLocal, ent.sWorld)
|
|
GGSM_ENTITY_ATTACH_TO_PARENT(ent, sGGSMData.sEntities[iParentEntity], TRUE)
|
|
ELSE
|
|
ent.sWorld = ent.sLocal
|
|
ENDIF
|
|
|
|
IF NOT bIsFriendly
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
IF (bCountTowardsTakedown = FALSE)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_NO_TAKEDOWN_BONUS)
|
|
ELSE
|
|
sGGSMData.iEnemiesCreated ++
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (ent.iGroupID != GGSM_INVALID_GROUP_ID)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntityGroup[ent.iGroupID].eFlags, GGSM_GROUP_BIT_END_WHEN_ALL_OFFSCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(ent.eFlags, GGSM_ENTITY_BIT_REMOVE_WHEN_OFFSCREEN)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CDEBUG1LN(DEBUG_MINIGAME, "GGSM_ENTITY_INIT - IND:", GGSM_ENTITY_GET_ARRAY_INDEX(ent), " TYPE:", GGSM_ENTITY_TYPE_TO_STRING(eType),
|
|
" LOCAL:[", ent.sLocal.vPosition.x, ", ", ent.sLocal.vPosition.y, "] ",
|
|
" WORLD:[", ent.sWorld.vPosition.x, ", ", ent.sWorld.vPosition.y, "]")
|
|
|
|
GGSM_COLLIDER_TRANSFORM(ent.sCollider, ent.sWorld, entData.sCollisionData)
|
|
//GGSM_ENTITY_UPDATE(ent)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_CONFIGURE_FROM_FORMATION(GGSM_ENTITY &ent, GGSM_FORMATION_DATA &dat)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(ent, GGSM_FORMATION_GET_MOVEMENT_TYPE(dat))
|
|
GGSM_ENTITY_SET_PATH_INDEX(ent, GGSM_FORMATION_GET_PATH_INDEX(dat))
|
|
|
|
IF (GGSM_FORMATION_GET_WEAPON_TYPE(dat) != GGSM_WEAPON_DEFAULT)
|
|
GGSM_ENTITY_SET_WEAPON(ent, GGSM_FORMATION_GET_WEAPON_TYPE(dat))
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_DETONATE_ENTITY_GROUP(GGSM_ENTITY_GROUP &group)
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(sGGSMData.sEntities) i
|
|
IF IS_BIT_SET(group.iMemberBitSet, i)
|
|
GGSM_ENTITY_EXPLODE(sGGSMData.sEntities[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
ENDPROC
|
|
|
|
PROC GGSM_DETONATE_ENTITIES_OF_TYPE(GGSM_ENTITY_TYPE eType)
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(sGGSMData.sEntities) i
|
|
IF (sGGSMData.sEntities[i].eType = eType)
|
|
GGSM_ENTITY_EXPLODE(sGGSMData.sEntities[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_DESTROY_ENTITIES_OF_TYPE(GGSM_ENTITY_TYPE eType)
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(sGGSMData.sEntities) i
|
|
IF (sGGSMData.sEntities[i].eType = eType)
|
|
GGSM_ENTITY_DESTROY(sGGSMData.sEntities[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_DESTROY_ENTITIES_OF_FACTION(BOOL bAllied)
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(sGGSMData.sEntities) i
|
|
IF (IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[i].eFlags, GGSM_ENTITY_BIT_IS_PLAYER_ALLIED) = bAllied)
|
|
GGSM_ENTITY_DESTROY(sGGSMData.sEntities[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
FUNC BOOL GGSM_BOSS_BREAD_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader, iGroupID, iChump
|
|
|
|
// find free group
|
|
iGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
IF (iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create smoothie
|
|
IF (GGSM_COUNT_FREE_ENTITIES(sGGSMData.sEntities) < 5)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeader, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create granana
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_BREAD)
|
|
boss.iGroupID = iGroupID
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeader], GGSM_ENTITY_BOSS_BREAD_FACE, INIT_VECTOR_2D(2400, 540))
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iLeader], GGSM_BOSS_SECTION_BREAD_FACE)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeader], iGroupID)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iLeader], 5)
|
|
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_BREAD_TOP_LEFT, INIT_VECTOR_2D(0, 0), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_BREAD_TOP_LEFT, FALSE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 4)
|
|
IF (sGGSMData.bHardMode)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
ENDIF
|
|
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_BREAD_BOTTOM_LEFT, INIT_VECTOR_2D(0, 0), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_BREAD_BASE_LEFT, FALSE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 3)
|
|
IF (sGGSMData.bHardMode)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
ENDIF
|
|
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_BREAD_TOP_RIGHT, INIT_VECTOR_2D(0, 0), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_BREAD_TOP_RIGHT, FALSE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 2)
|
|
IF (sGGSMData.bHardMode)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
ENDIF
|
|
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_BREAD_BOTTOM_RIGHT, INIT_VECTOR_2D(0, 0), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_BREAD_BASE_RIGHT, FALSE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 1)
|
|
IF (sGGSMData.bHardMode)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
ENDIF
|
|
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_BREAD_EYEBROWS, INIT_VECTOR_2D(-40, -80), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_BREAD_BROWS, FALSE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iChump], GGSM_SPRITE_ANIM_BREAD_EYEBROWS)
|
|
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_BOSS_START")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_BOSS_DR_DANK_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader, iChump
|
|
INT iGroupID
|
|
|
|
// find free group
|
|
iGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
IF (iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create smoothie
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeader, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create granana
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_DR_DANK)
|
|
boss.iGroupID = iGroupID
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_DR_DANK)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeader], GGSM_ENTITY_BOSS_DR_DANK_TOP, INIT_VECTOR_2D(2400, 540))
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_DANK_SCATTER)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iLeader], 2)
|
|
sGGSMData.sEntities[iLeader].iNumShotsOverride = 5
|
|
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iLeader], GGSM_BOSS_SECTION_DR_DANK_TOP)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeader], iGroupID)
|
|
|
|
// create wig
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_MIDDLE, INIT_VECTOR_2D(0, 240), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_MIDDLE, FALSE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DIE_ONLY_FROM_EXPLOSIONS)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 1)
|
|
|
|
// create glasses
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_BOTTOM, INIT_VECTOR_2D(0, 290), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_BOTTOM, FALSE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DIE_ONLY_FROM_EXPLOSIONS)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
|
|
// create rockets launchers
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_RLAUNCHER, INIT_VECTOR_2D(-137, -22), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_ROCKET_L1, FALSE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_RLAUNCHER, INIT_VECTOR_2D(94, -21), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_ROCKET_R1, FALSE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_RHLAUNCHER, INIT_VECTOR_2D(-93, 17), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_ROCKET_L2, FALSE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_DR_DANK_RHLAUNCHER, INIT_VECTOR_2D(34, 28), DEFAULT, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_DR_DANK_ROCKET_R2, FALSE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iChump], 0)
|
|
ENDIF
|
|
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_FINAL_BOSS_START")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_BOSS_GRANANA_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader, iChump
|
|
INT iGroupID
|
|
|
|
// find free group
|
|
iGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
IF (iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create smoothie
|
|
IF (GGSM_COUNT_FREE_ENTITIES(sGGSMData.sEntities) < 3)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeader, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create granana
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_GRANANA)
|
|
boss.iGroupID = iGroupID
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeader], GGSM_ENTITY_BOSS_GRANANA, INIT_VECTOR_2D(2400, 540))
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iLeader], GGSM_SPRITE_ANIM_GRANANA)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iLeader], 2)
|
|
sGGSMData.sEntities[iLeader].iNumShotsOverride = 2
|
|
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iLeader], GGSM_BOSS_SECTION_GRANANA)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeader], iGroupID)
|
|
|
|
// create wig
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_GRANANA_HAIR, INIT_VECTOR_2D(-80, -160), 0, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_GRANANA_HAIR)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
|
|
// create glasses
|
|
GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_GRANANA_GLASSES, INIT_VECTOR_2D(-20, -60), 0, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYLASER)
|
|
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_BOSS_START")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_BOSS_MARINE_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader, iGroupID
|
|
INT iChump
|
|
|
|
// find free group
|
|
iGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
IF (iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create smoothie
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeader, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create granana
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_MARINE)
|
|
boss.iGroupID = iGroupID
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntityGroup[iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeader], GGSM_ENTITY_BOSS_MARINE, INIT_VECTOR_2D(2400, 540))
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iLeader], GGSM_SPRITE_ANIM_MARINE)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iLeader], GGSM_BOSS_SECTION_MARINE)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeader], iGroupID)
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_BOSS_MARINE_LAUNCHER, INIT_VECTOR_2D(-176, 56), 0, DEFAULT, iLeader)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iChump], GGSM_BOSS_SECTION_MARINE_LAUNCHER, FALSE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_DAMAGE_HURTS_ROOT)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_NONE)
|
|
ENDIF
|
|
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_BOSS_START")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_BOSS_SMOOTHIE_CREATE_ORBITERS(GGSM_BOSS_CONTROLLER &boss, INT iNumber = 5)
|
|
INT n, iChump
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_SMOOTHIE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (sGGSMData.bHardMode)
|
|
iNumber += 3
|
|
ENDIF
|
|
|
|
FLOAT fAngleDiff = 360.0 / TO_FLOAT(iNumber)
|
|
FLOAT fAngle = GET_RANDOM_FLOAT_IN_RANGE(0, 360)
|
|
REPEAT iNumber n
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_CIRCLE_SHIP_YELLOW, INIT_VECTOR_2D(0, 0), 0, FALSE, iLeader, FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iChump], GGSM_MOVEMENT_ORBIT, 300.0, fAngle + (n * fAngleDiff), 0.5)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_ENEMYSHOT)
|
|
sGGSMData.sEntities[iChump].iHP = 3
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iChump].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_BOSS_SMOOTHIE_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader, iGroupID
|
|
|
|
// find free group
|
|
iGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
IF (iGroupID = GGSM_INVALID_GROUP_ID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// create smoothie
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeader, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
GGSM_RESET_BOSS_CONTROLLER(boss, GGSM_BOSS_SMOOTHIE)
|
|
boss.iGroupID = iGroupID
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGroupID].eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGroupID].eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeader], GGSM_ENTITY_BOSS_SMOOTHIE, INIT_VECTOR_2D(2400, 540))
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iLeader], GGSM_SPRITE_ANIM_SMOOTHIE)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeader], iGroupID)
|
|
GGSM_ADD_ENTITY_TO_BOSS_CONTROLLER(boss, sGGSMData.sEntities[iLeader], GGSM_BOSS_SECTION_SMOOTHIE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_SMOOTHIESPREAD)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iLeader], 2)
|
|
|
|
GGSM_BOSS_SMOOTHIE_CREATE_ORBITERS(boss)
|
|
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_BOSS_START")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_BOSS_INIT(GGSM_BOSS_CONTROLLER &boss)
|
|
SWITCH (boss.eType)
|
|
CASE GGSM_BOSS_BREAD RETURN GGSM_BOSS_BREAD_INIT(boss)
|
|
CASE GGSM_BOSS_DR_DANK RETURN GGSM_BOSS_DR_DANK_INIT(boss)
|
|
CASE GGSM_BOSS_GRANANA RETURN GGSM_BOSS_GRANANA_INIT(boss)
|
|
CASE GGSM_BOSS_MARINE RETURN GGSM_BOSS_MARINE_INIT(boss)
|
|
CASE GGSM_BOSS_SMOOTHIE RETURN GGSM_BOSS_SMOOTHIE_INIT(boss)
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER SMOOTHIE FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_A(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_SMOOTHIE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer >= 0.5)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_RANDOM_SPREAD)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_SMOOTHIESPREAD)
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(2, 4)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_BURST_RELOAD_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_B(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_SMOOTHIE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
IF (boss.fStateTimer >= 1.25)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_RANDOM_SPREAD)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_SMOOTHIEVULCAN)
|
|
boss.iInternalCounter = 0
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_BURST_RELOAD_THIS_FRAME)
|
|
boss.iInternalCounter ++
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter >= 3)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_C(GGSM_BOSS_CONTROLLER &boss)
|
|
FLOAT f
|
|
INT iChump
|
|
VECTOR_2D v
|
|
FLOAT t
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_SMOOTHIE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(2000, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
IF (boss.iSubGroupID != GGSM_INVALID_GROUP_ID)
|
|
GGSM_DETONATE_ENTITY_GROUP(sGGSMData.sEntityGroup[boss.iSubGroupID])
|
|
ENDIF
|
|
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_DESTROY_ENTITIES_OF_TYPE(GGSM_ENTITY_CIRCLE_SHIP_YELLOW)
|
|
boss.iSubGroupID = GGSM_GET_FREE_ENTITY_GROUP(sGGSMData.sEntityGroup)
|
|
|
|
IF (boss.iSubGroupID != GGSM_INVALID_GROUP_ID)
|
|
GGSM_RESET_ENTITY_GROUP(sGGSMData.sEntityGroup[boss.iSubGroupID])
|
|
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(6, 10)
|
|
ELSE
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(3, 5)
|
|
ENDIF
|
|
|
|
IF (sGGSMData.bHardMode)
|
|
boss.iInternalCounter += 3
|
|
ENDIF
|
|
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 2
|
|
t = 0.25
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
t = 0.125
|
|
ENDIF
|
|
|
|
IF (boss.fStateTimer >= t)
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
f = GET_RANDOM_FLOAT_IN_RANGE(800.0, 900.0)
|
|
v = GGSM_GET_VECTOR_FROM_HEADING(GET_RANDOM_FLOAT_IN_RANGE(0, 360))
|
|
v.x *= f
|
|
v.y *= f
|
|
v.x += cfBASE_SCREEN_HALF_WIDTH
|
|
v.y += cfBASE_SCREEN_HALF_HEIGHT
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_CHERRYBOMB, v, 0, FALSE, DEFAULT, FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iChump], GGSM_MOVEMENT_DESTRUCT_ON_IMPACT)
|
|
GGSM_ENTITY_SET_TARGET_WORLD_VECTOR(sGGSMData.sEntities[iChump], GGSM_GET_TARGET_AT_PLAYER_POSITION())
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_NONE)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iChump], boss.iSubGroupID)
|
|
|
|
boss.iInternalCounter --
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF (boss.iSubGroupID != GGSM_INVALID_GROUP_ID) AND GGSM_ENTITY_GROUP_HAS_GROUP_FINISHED(sGGSMData.sEntityGroup[boss.iSubGroupID])
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1450, 540))
|
|
|
|
iChump = 5
|
|
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
GGSM_BOSS_SMOOTHIE_CREATE_ORBITERS(boss, iChump + 2)
|
|
ELSE
|
|
GGSM_BOSS_SMOOTHIE_CREATE_ORBITERS(boss, iChump)
|
|
ENDIF
|
|
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 4
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_SMOOTHIE_SELECT_ATTACK_PATTERN(GGSM_BOSS_CONTROLLER &boss)
|
|
INT i = GET_RANDOM_INT_IN_RANGE(0, 3)
|
|
|
|
SWITCH (i)
|
|
CASE 0
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_PATTERN_B)
|
|
BREAK
|
|
CASE 1
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_PATTERN_C)
|
|
BREAK
|
|
DEFAULT
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_SMOOTHIE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_ARRIVE
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1350, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.bStateInit = TRUE
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_SMOOTHIE_START)
|
|
GGSM_BOSS_CONTROLLER_SET_ATTACK_PATTERN(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_ACTIVE
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_A
|
|
GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_A(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_B
|
|
GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_B(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_C
|
|
GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE_PATTERN_C(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_D
|
|
CASE GGSM_BOSS_STATE_PATTERN_E
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PLAYER_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_SMOOTHIE_FAILED)
|
|
boss.bStateInit = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_SMOOTHIE_DEFEATED)
|
|
boss.bStateInit = TRUE
|
|
ELIF NOT GGSM_IS_DIALOG_ACTIVE()
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DONE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER BREAD FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
FUNC INT GGSM_BOSS_CONTROLLER_COUNT_BREAD_SLICES(GGSM_BOSS_CONTROLLER &boss)
|
|
INT cnt = 0
|
|
INT i, ind
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, 1 + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
cnt ++
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN cnt
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(GGSM_BOSS_CONTROLLER &boss)
|
|
INT i, ind
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, 1 + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
IF NOT GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[ind])
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_EXPLODE_BREAD(GGSM_BOSS_CONTROLLER &boss, FLOAT spdScalar = 1.0)
|
|
INT i, ind
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
BOOL bPlaySound = FALSE
|
|
VECTOR_2D vPos, vDir
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_BASE_LEFT + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(sGGSMData.sEntities[ind])
|
|
vDir = GGSM_GET_VECTOR_FROM_HEADING(45.0 + (i * 90.0))
|
|
vPos = sGGSMData.sEntities[iLeader].sWorld.vPosition
|
|
vPos.x += (vDir.x * 800.0)
|
|
vPos.y += (vDir.y * 800.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[ind], vPos)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[ind], spdScalar)
|
|
bPlaySound = TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF (bPlaySound)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_BREAD_SPLIT, sGGSMData.sEntities[iLeader].sWorld.vPosition)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_DISPERSE_BREAD(GGSM_BOSS_CONTROLLER &boss, VECTOR_2D vPos, FLOAT fDelay = 0.0, FLOAT spdScalar = 1.0)
|
|
INT i, ind
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
BOOL bPlaySound = FALSE
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, 1 + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(sGGSMData.sEntities[ind])
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[ind], vPos, fDelay * i)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[ind], spdScalar)
|
|
bPlaySound = TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF (bPlaySound)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_BREAD_SPLIT, sGGSMData.sEntities[iLeader].sWorld.vPosition)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_REASSEMBLE_BREAD(GGSM_BOSS_CONTROLLER &boss)
|
|
INT i, ind
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
BOOL bPlaySound = FALSE
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_BASE_LEFT + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_ENTITY_ATTACH_TO_PARENT(sGGSMData.sEntities[ind], sGGSMData.sEntities[iLeader])
|
|
GGSM_ENTITY_RETURN_TO_ORIGIN(sGGSMData.sEntities[ind])
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[ind])
|
|
bPlaySound = TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF (bPlaySound)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_BREAD_ASSEMBLE, sGGSMData.sEntities[iLeader].sWorld.vPosition)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_A(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
INT iMouthCover = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_BASE_LEFT)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 1.0)
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[iLeader])
|
|
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_BOSS_CONTROLLER_EXPLODE_BREAD(boss)
|
|
boss.iInternalCounter = 0
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_BREADSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_DISPERSE_BREAD(boss, GGSM_GET_TARGET_AT_PLAYER_POSITION())
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF (boss.fStateTimer > 3.0)
|
|
GGSM_BOSS_CONTROLLER_EXPLODE_BREAD(boss)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 4
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
GGSM_BOSS_CONTROLLER_REASSEMBLE_BREAD(boss)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 5
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_B(GGSM_BOSS_CONTROLLER &boss)
|
|
VECTOR_2D vTarget
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
INT iMouthCover = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_BASE_LEFT)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.5)
|
|
vTarget = INIT_VECTOR_2D(540, 540)
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (sGGSMData.sEntities[iLeader].sWorld.vPosition.x < cfBASE_SCREEN_HALF_WIDTH)
|
|
vTarget = INIT_VECTOR_2D(1400, 540)
|
|
ENDIF
|
|
|
|
GGSM_BOSS_CONTROLLER_DISPERSE_BREAD(boss, vTarget, 0.5, 2.0)
|
|
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_BREADSPREAD)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], vTarget, 3.0)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iLeader], 2.0)
|
|
boss.iInternalCounter = 0
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 2.0)
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
GGSM_BOSS_CONTROLLER_DISPERSE_BREAD(boss, INIT_VECTOR_2D(1400, 540), 0.5, 2.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1400, 540), 3.0)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iLeader], 2.0)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_REASSEMBLE_BREAD(boss)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 4
|
|
IF GGSM_BOSS_CONTROLLER_HAVE_BREAD_SLICES_STOPPED_MOVING(boss)
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_C(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iChump
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
INT iMouthCover = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_BASE_LEFT)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.25)
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1010.0, 300.0))
|
|
boss.iInternalCounter = 0
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(7, 11)
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 0.25)
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iChump, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iChump], GGSM_ENTITY_CRUMB_METEOR, INIT_VECTOR_2D(GET_RANDOM_FLOAT_IN_RANGE(400.0, 1500.0), 0.0), 0, FALSE, DEFAULT, FALSE)
|
|
sGGSMData.sEntities[iChump].vLocalDirection = INIT_VECTOR_2D(0, 1)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iChump], GGSM_MOVEMENT_STRAIGHT)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iChump], GGSM_WEAPON_NONE)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iChump], GET_RANDOM_FLOAT_IN_RANGE(0.75, 1.25))
|
|
boss.iInternalCounter --
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF (boss.fStateTimer > 1.0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1400.0, 540.0))
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 4
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
|
|
IF (iMouthCover != GGSM_INVALID_ENTITY)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_BREAD(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_BREAD_FACE)
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_ARRIVE
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1400, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.bStateInit = TRUE
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_BREAD_START)
|
|
GGSM_BOSS_CONTROLLER_SET_ATTACK_PATTERN(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_ACTIVE
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_A
|
|
GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_A(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_B
|
|
GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_B(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_C
|
|
GGSM_BOSS_CONTROLLER_UPDATE_BREAD_PATTERN_C(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_D
|
|
CASE GGSM_BOSS_STATE_PATTERN_E
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PLAYER_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_BREAD_FAILED)
|
|
boss.bStateInit = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_BREAD_DEFEATED)
|
|
boss.bStateInit = TRUE
|
|
ELIF NOT GGSM_IS_DIALOG_ACTIVE()
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DONE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER GRANANA FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_GRANANA_CRACK_GLASSES(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iGlasses = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
|
|
IF (iGlasses = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGlasses], 2, TRUE)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_DAMAGE, sGGSMData.sEntities[iGlasses].sWorld.vPosition)
|
|
CPRINTLN(DEBUG_MINIGAME, "GGSM_BOSS_CONTROLLER_GRANANA_CRACK_GLASSES")
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_A(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA)
|
|
INT iGlasses = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
INT iHair = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_HAIR)
|
|
|
|
FLOAT fHPPerc = GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (fHPPerc > 0.5)
|
|
sGGSMData.sEntities[iLeader].iNumShotsOverride = 2
|
|
ELSE
|
|
sGGSMData.sEntities[iLeader].iNumShotsOverride = 4
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
ARCADE_GAMES_SOUND_STOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iHair].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1)
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[iGlasses])
|
|
|
|
IF (fHPPerc > 0.5)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGlasses], 0, TRUE)
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iGlasses], 2.0)
|
|
ELSE
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGlasses], 2, TRUE)
|
|
ENDIF
|
|
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(6, 12)
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1A)
|
|
ELSE
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
IF (boss.iInternalCounter > 0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(GET_RANDOM_FLOAT_IN_RANGE(1200, 1450), GET_RANDOM_FLOAT_IN_RANGE(500, 740)))
|
|
ELSE
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_B(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA)
|
|
INT iGlasses = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
INT iHair = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_HAIR)
|
|
FLOAT fHPPerc = GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_ALT_SPREAD)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1A)
|
|
ELSE
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1355, 900))
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iLeader], 3.0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iHair].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_GRANANASPREAD1)
|
|
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(sGGSMData.sEntities[iHair])
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iHair], GGSM_WEAPON_GRANANAHAIR)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_DAMAGE_LOSE_WIG, sGGSMData.sEntities[iHair].sWorld.vPosition)
|
|
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iHair].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iHair].eFlags, GGSM_ENTITY_BIT_WPN_FIRE_ON_ARRIVE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iHair], GGSM_MOVEMENT_TARGETTED_WANDER, 0.125)
|
|
|
|
IF (fHPPerc < 0.5)
|
|
sGGSMData.sEntities[iHair].iNumShotsOverride = 6
|
|
GGSM_ENTITY_SCALE_BASE_SPEED(sGGSMData.sEntities[iHair], 1.5)
|
|
ENDIF
|
|
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(4, 6)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iHair].eMoveFlags, GGSM_MOVE_BIT_TARGET_POINT_REACHED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iHair], GGSM_WEAPON_NONE)
|
|
GGSM_ENTITY_ATTACH_TO_PARENT(sGGSMData.sEntities[iHair], sGGSMData.sEntities[iLeader])
|
|
GGSM_ENTITY_RETURN_TO_ORIGIN(sGGSMData.sEntities[iHair])
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[iHair])
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iHair].eFlags, GGSM_ENTITY_BIT_WPN_FIRE_ON_ARRIVE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1450, 540))
|
|
GGSM_ENTITY_RESET_BASE_SPEED(sGGSMData.sEntities[iLeader])
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_C(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA)
|
|
INT iGlasses = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
FLOAT fHPPerc = GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
ARCADE_GAMES_SOUND_PLAY_LOOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
IF (fHPPerc > 0.5)
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iGlasses], GGSM_SPRITE_ANIM_GRAN_GLASS)
|
|
ELSE
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iGlasses], GGSM_SPRITE_ANIM_GRAN_GLASSCRACK)
|
|
ENDIF
|
|
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF (boss.fStateTimer > 3.0)
|
|
IF (fHPPerc > 0.5)
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGlasses], 1, TRUE)
|
|
ELSE
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGlasses], 3, TRUE)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0.0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 1.0)
|
|
ARCADE_GAMES_SOUND_STOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
IF (fHPPerc < 0.5)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGlasses], GGSM_WEAPON_GRANANAGLASSES2)
|
|
ELSE
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGlasses], GGSM_WEAPON_GRANANAGLASSES)
|
|
ENDIF
|
|
GGSM_ENTITY_FIRE_WEAPON(sGGSMData.sEntities[iGlasses])
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_BURST_FIRED)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_GRANANA(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA)
|
|
INT iGlasses = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_GRANANA_GLASSES)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (boss.eState > GGSM_BOSS_STATE_ARRIVE)
|
|
IF (boss.bFiftyPercent = FALSE) AND (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
GGSM_BOSS_CONTROLLER_GRANANA_CRACK_GLASSES(boss)
|
|
boss.bFiftyPercent = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_ARRIVE
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1450, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGlasses].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.bStateInit = TRUE
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_BOSS_CONTROLLER_SET_ATTACK_PATTERN(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_GRANANA_START)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_ACTIVE
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_A
|
|
GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_A(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_B
|
|
GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_B(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_C
|
|
GGSM_BOSS_CONTROLLER_UPDATE_GRANANA_PATTERN_C(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_D
|
|
CASE GGSM_BOSS_STATE_PATTERN_E
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PLAYER_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
ARCADE_GAMES_SOUND_STOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_GRANANA_FAILED)
|
|
boss.bStateInit = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
ARCADE_GAMES_SOUND_STOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_GRANANA_DEFEATED)
|
|
boss.bStateInit = TRUE
|
|
ELIF NOT GGSM_IS_DIALOG_ACTIVE()
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DONE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER MARINE FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_MARINE_CHESTBURST(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iLeader], GGSM_SPRITE_ANIM_MARINE_ALIEN)
|
|
GGSM_PLAY_SOUND_FROM_POSITION(ARCADE_GAMES_SOUND_GGSM_BOSS_MARINE_CHESTBURST, sGGSMData.sEntities[iLeader].sWorld.vPosition)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_A(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
INT iLauncher = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE_LAUNCHER)
|
|
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) OR (iLauncher = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.5)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_MARINE_SPREAD)
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(7, 11)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 0.5)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_B(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
INT iLauncher = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE_LAUNCHER)
|
|
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) OR (iLauncher = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.5)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLauncher], GGSM_WEAPON_MARINE_LAUNCHER)
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(5, 10)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (sGGSMData.iEnemyProjectilesActive = 0)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3
|
|
IF (boss.fStateTimer > 0.1)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_C(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
INT iLauncher = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE_LAUNCHER)
|
|
FLOAT hprc = GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss)
|
|
|
|
IF (hprc > 0.5) OR (hprc < 0.25)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.5)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_RANDOM_SPREAD)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_ACID_VULKAN)
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(10, 15)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 0.5)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_D(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
INT iLauncher = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE_LAUNCHER)
|
|
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) > 0.25)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (boss.fStateTimer > 0.5)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLauncher].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_RANDOM_SPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_SINGLE_SHOT_MODE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_ACID)
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(10, 15)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
boss.fStateTimer = 0
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF (boss.fStateTimer > 0.5)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_MARINE(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_MARINE)
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (boss.bFiftyPercent = FALSE)
|
|
IF (iLeader != GGSM_INVALID_ENTITY) AND (boss.eState > GGSM_BOSS_STATE_ARRIVE)
|
|
IF (GGSM_BOSS_CONTROLLER_GET_HP_PERCENTAGE(boss) < 0.5)
|
|
GGSM_BOSS_CONTROLLER_MARINE_CHESTBURST(boss)
|
|
boss.bFiftyPercent = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_ARRIVE
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1350, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
boss.bStateInit = TRUE
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_BOSS_CONTROLLER_SET_ATTACK_PATTERN(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_ENEMYCONESPREAD)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_MARINE_START)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_ACTIVE
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_A
|
|
GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_A(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_B
|
|
GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_B(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_C
|
|
GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_C(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_D
|
|
GGSM_BOSS_CONTROLLER_UPDATE_MARINE_PATTERN_D(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_E
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PLAYER_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_MARINE_FAILED)
|
|
boss.bStateInit = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_MARINE_DEFEATED)
|
|
boss.bStateInit = TRUE
|
|
ELIF NOT GGSM_IS_DIALOG_ACTIVE()
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DONE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER DR_DANK FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_DR_DANK_ACTIVATE_ROCKETS(GGSM_BOSS_CONTROLLER &boss, BOOL bOn = TRUE)
|
|
INT i, ind
|
|
|
|
REPEAT 4 i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_ROCKET_L1 + i)
|
|
IF (ind != GGSM_INVALID_ENTITY) AND (sGGSMData.sEntities[ind].eState = GGSM_ENTITY_STATE_ALIVE)
|
|
IF (bOn)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_A(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_TOP)
|
|
INT iGunSection = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_BOTTOM)
|
|
VECTOR_2D vTarget, vPlayerPos
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (iGunSection = GGSM_INVALID_ENTITY)
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0 // detach gun
|
|
GGSM_BOSS_CONTROLLER_DEACTIVATE_ALL_WEAPONS(boss)
|
|
GGSM_ENTITY_DETACH_FROM_PARENT(sGGSMData.sEntities[iGunSection])
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGunSection], GGSM_WEAPON_DANK_CANNON)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], INIT_VECTOR_2D(1890, 820))
|
|
boss.iBossPatternState ++
|
|
BREAK
|
|
|
|
CASE 1 // move gun to top of screen and move down wards
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iGunSection])
|
|
GGSM_ENTITY_SET_LOCAL_TRANSFORM(sGGSMData.sEntities[iGunSection], 1470, 0, 270)
|
|
GGSM_ENTITY_SET_ANIMATION(sGGSMData.sEntities[iGunSection], GGSM_SPRITE_ANIM_DANK_CANNON)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], INIT_VECTOR_2D(1470, 70), 0.125)
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(2, 5)
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2 // start moving gun across
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iGunSection])
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(2, 5)
|
|
GGSM_BOSS_CONTROLLER_DR_DANK_ACTIVATE_ROCKETS(boss, TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], INIT_VECTOR_2D(390, 70))
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 3 // if player cross the line of gun shoot - if we've moved across so many times the return gun
|
|
vPlayerPos = GGSM_GET_TARGET_AT_PLAYER_POSITION()
|
|
|
|
IF (ABSF(vPlayerPos.x - sGGSMData.sEntities[iGunSection].sWorld.vPosition.x) < 128.0)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iGunSection])
|
|
boss.iInternalCounter --
|
|
vTarget = sGGSMData.sEntities[iGunSection].sWorld.vPosition
|
|
|
|
IF (boss.iInternalCounter <= 0)
|
|
vTarget = sGGSMData.sEntities[iGunSection].sWorld.vPosition
|
|
vTarget.y -= 100.0
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], vTarget)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.iBossPatternState ++
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF (sGGSMData.sEntities[iGunSection].vLocalDirection.x < 0)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], INIT_VECTOR_2D(1470, vTarget.y))
|
|
ELSE
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iGunSection], INIT_VECTOR_2D(390, vTarget.y))
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 4 // put gun back
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iGunSection])
|
|
GGSM_ENTITY_SET_ANIM_FRAME(sGGSMData.sEntities[iGunSection], DEFAULT, TRUE)
|
|
GGSM_ENTITY_SET_LOCAL_TRANSFORM(sGGSMData.sEntities[iGunSection], 1890, 820, 0)
|
|
GGSM_ENTITY_SET_PARENT_INDEX(sGGSMData.sEntities[iGunSection], iLeader)
|
|
GGSM_ENTITY_RETURN_TO_ORIGIN(sGGSMData.sEntities[iGunSection])
|
|
boss.iBossPatternState ++
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 5 // turn rockets off
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iGunSection])
|
|
GGSM_BOSS_CONTROLLER_DR_DANK_ACTIVATE_ROCKETS(boss, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_B(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iGunSection = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_MIDDLE)
|
|
|
|
IF (iGunSection = GGSM_INVALID_ENTITY)
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGunSection], GGSM_WEAPON_DANK_CLUSTERBOMB)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
sGGSMData.sEntities[iGunSection].iNumShotsOverride = 4
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(4, 8)
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter < 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_C(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iGunSection = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_MIDDLE)
|
|
|
|
IF (iGunSection = GGSM_INVALID_ENTITY)
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGunSection], GGSM_WEAPON_DANK_SPREAD)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ALT_SPREAD)
|
|
sGGSMData.sEntities[iGunSection].iNumShotsOverride = 4
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(4, 8)
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter < 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_D(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_TOP)
|
|
INT iGunSection = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_BOTTOM)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY)
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.iBossPatternState)
|
|
CASE 0
|
|
IF (iGunSection != GGSM_INVALID_ENTITY)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iGunSection], GGSM_WEAPON_DANK_CANNON)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iGunSection].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeader], GGSM_WEAPON_DANK_SCATTER)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
|
|
boss.iBossPatternState ++
|
|
boss.iInternalCounter = GET_RANDOM_INT_IN_RANGE(10, 15)
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_FIRED_THIS_FRAME)
|
|
boss.iInternalCounter --
|
|
ENDIF
|
|
|
|
IF (boss.iInternalCounter < 0)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ACTIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK(GGSM_BOSS_CONTROLLER &boss)
|
|
INT iLeader = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_TOP)
|
|
//INT iGunSection = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, GGSM_BOSS_SECTION_DR_DANK_BOTTOM)
|
|
|
|
IF (iLeader = GGSM_INVALID_ENTITY) AND (boss.eState >= GGSM_BOSS_STATE_ARRIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_ARRIVE
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TO_VECTOR(sGGSMData.sEntities[iLeader], INIT_VECTOR_2D(1350, 540))
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeader].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
boss.bStateInit = TRUE
|
|
ELIF IS_BITMASK_ENUM_AS_ENUM_SET(sGGSMData.sEntities[iLeader].eMoveFlags, GGSM_MOVE_BIT_COMPLETE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[iLeader], GGSM_MOVEMENT_NONE)
|
|
GGSM_BOSS_CONTROLLER_SET_ATTACK_PATTERN(boss, GGSM_BOSS_STATE_PATTERN_A)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_DR_DANK_START)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_ACTIVE
|
|
IF GGSM_ENTITY_IS_MOVEMENT_COMPLETE(sGGSMData.sEntities[iLeader])
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_A
|
|
GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_A(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_B
|
|
GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_B(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_C
|
|
GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_C(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_D
|
|
GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK_PATTERN_D(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PATTERN_E
|
|
GGSM_BOSS_CONTROLLER_SELECT_ATTACK_PATTERN(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_PLAYER_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_DR_DANK_FAILED)
|
|
boss.bStateInit = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_DEAD
|
|
IF (boss.bStateInit = FALSE)
|
|
GGSM_DIALOG_CONTROLLER_START_DIALOG(sGGSMData.sDialogController, GGSM_DIALOG_BOSS_DR_DANK_DEFEATED)
|
|
boss.bStateInit = TRUE
|
|
ELIF NOT GGSM_IS_DIALOG_ACTIVE()
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DONE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// BOSS CONTROLLER FUNCTION
|
|
//-------------------------------------------------
|
|
|
|
FUNC BOOL GGSM_BOSS_CONTROLLER_UPDATE(GGSM_BOSS_CONTROLLER &boss)
|
|
INT i, ind
|
|
|
|
IF (boss.eType = GGSM_BOSS_NONE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF (boss.eState = GGSM_BOSS_STATE_DONE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
boss.fStateTimer += (GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
boss.iTotalHP = GGSM_BOSS_CONTROLLER_GET_HP(boss)
|
|
|
|
// don't let people shoot while the boss is loading
|
|
IF (boss.eState >= GGSM_BOSS_STATE_LOADING) AND (boss.eState < GGSM_BOSS_STATE_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_DISABLE_WEAPONS)
|
|
GGSM_SET_PLAYER_INVUNERABLE()
|
|
ELSE
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_DISABLE_WEAPONS)
|
|
ENDIF
|
|
|
|
// handle defeated player state
|
|
IF (boss.eState != GGSM_BOSS_STATE_PLAYER_DEAD)
|
|
IF GGSM_IS_PLAYER_TOTALLY_DEFEATED()
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_PLAYER_DEAD)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// handle boss dead state
|
|
IF (boss.eState != GGSM_BOSS_STATE_DEAD)
|
|
IF (boss.iMaxTotalHP > 0) AND (boss.iTotalHP = 0)
|
|
boss.iMaxTotalHP = 0
|
|
|
|
GGSM_RESET_PROJECTILE_ARRAY(sGGSMData.sProjectiles)
|
|
IF (boss.iSubGroupID != GGSM_INVALID_GROUP_ID)
|
|
GGSM_DETONATE_ENTITY_GROUP(sGGSMData.sEntityGroup[boss.iSubGroupID])
|
|
boss.iSubGroupID = GGSM_INVALID_GROUP_ID
|
|
ENDIF
|
|
|
|
ARCADE_GAMES_SOUND_STOP(ARCADE_GAMES_SOUND_GGSM_BOSS_GRAN_ATTACK_EYE_LASER_CHARGE_LOOP)
|
|
GGSM_ENTITY_EXPLODE_ARRAY(sGGSMData.sEntities, FALSE)
|
|
GGSM_TRIGGER_MUSIC_EVENT("ARCADE_SM_STOP")
|
|
GGSM_SHUTDOWN_ALL_SPECIAL_WEAPONS(sGGSMData.sSpWeaponData)
|
|
|
|
IF boss.eType = GGSM_BOSS_DR_DANK
|
|
GGSM_PLAY_AVATAR_ALL_CLEAR_ANIM()
|
|
ELSE
|
|
GGSM_PLAY_AVATAR_BOSS_DEAD_ANIM()
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_PLAYER_BOSS_INVUNERABLE)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_DEAD)
|
|
ENDIF
|
|
ELSE
|
|
IF (boss.fStateTimer > 15.0)
|
|
SCRIPT_ASSERT("EMERGENCY TIME OUT")
|
|
GGSM_DESTROY_ENTITIES_OF_FACTION(FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// remove dead units from the boss controller
|
|
IF (boss.iMaxTotalHP > 0)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_BRING_CAMERA_TO_STOP)
|
|
|
|
REPEAT GGSM_MAX_BOSS_PARTS i
|
|
ind = GGSM_BOSS_CONTROLLER_GET_ENTITY_INDEX(boss, i)
|
|
IF (ind != GGSM_INVALID_ENTITY)
|
|
IF (sGGSMData.sEntities[ind].eState != GGSM_ENTITY_STATE_ALIVE)
|
|
GGSM_BOSS_CONTROLLER_SET_ENTITY_INDEX(boss, i, GGSM_INVALID_ENTITY)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
|
|
// update standard states
|
|
SWITCH (boss.eState)
|
|
CASE GGSM_BOSS_STATE_NONE
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_LOADING)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_LOADING
|
|
IF GGSM_LOAD_TEXTURE_DICTS_FOR_BOSS(boss.eType)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_CREATE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_STATE_CREATE
|
|
IF GGSM_BOSS_INIT(boss)
|
|
GGSM_CLEAR_BOSS_CONTROLLER_USED_PATTERN_BITSET(boss)
|
|
GGSM_BOSS_CONTROLLER_SET_STATE(boss, GGSM_BOSS_STATE_ARRIVE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
// update boss specific states
|
|
SWITCH (boss.eType)
|
|
CASE GGSM_BOSS_BREAD
|
|
GGSM_BOSS_CONTROLLER_UPDATE_BREAD(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_DR_DANK
|
|
GGSM_BOSS_CONTROLLER_UPDATE_DR_DANK(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_GRANANA
|
|
GGSM_BOSS_CONTROLLER_UPDATE_GRANANA(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_MARINE
|
|
GGSM_BOSS_CONTROLLER_UPDATE_MARINE(boss)
|
|
BREAK
|
|
|
|
CASE GGSM_BOSS_SMOOTHIE
|
|
GGSM_BOSS_CONTROLLER_UPDATE_SMOOTHIE(boss)
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_BOSS_CONTROLLER_UPDATE_ARRAY(GGSM_BOSS_CONTROLLER &array[])
|
|
INT i
|
|
|
|
REPEAT COUNT_OF(array) i
|
|
IF GGSM_BOSS_CONTROLLER_UPDATE(array[i])
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.eStageFlags, GGSM_STAGE_BIT_BOSSES_ACTIVE)
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------
|
|
// GROUP UPDATE FUNCTIONS
|
|
//-------------------------------------------------
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_STANDARD(GGSM_ENTITY_GROUP &group)
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
FLOAT fDistBetweenUnits = FMAX(ABSF(spriteSize.x), ABSF(spriteSize.y)) * spacing.x
|
|
FLOAT spd = entData.fBaseSpeed
|
|
|
|
// move the dist counter so we can ensure the formation is reasonably spaced
|
|
group.fDistCounter += (spd * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
group.fDistCounter = CLAMP(group.fDistCounter, 0, fDistBetweenUnits)
|
|
IF (group.fDistCounter < fDistBetweenUnits)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT ind
|
|
VECTOR_2D vBasePos
|
|
|
|
// create leader
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
EXIT
|
|
ENDIF
|
|
|
|
vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
group.fDistCounter = 0
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_DELAYED_LINE(GGSM_ENTITY_GROUP &group, VECTOR_2D vSpreadDir)
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
FLOAT fDistBetweenUnits = FMAX(ABSF(spriteSize.x), ABSF(spriteSize.y)) * spacing.x
|
|
FLOAT spd = entData.fBaseSpeed
|
|
|
|
// move the dist counter so we can ensure the formation is reasonably spaced
|
|
group.fDistCounter += (spd * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
group.fDistCounter = CLAMP(group.fDistCounter, 0, fDistBetweenUnits)
|
|
IF (group.fDistCounter < fDistBetweenUnits)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT ind
|
|
|
|
// create leader
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT iFormIndex = GGSM_FORMATION_GET_MEMBER_COUNT(group.sFormSettings) - group.iMembersToCreate
|
|
VECTOR_2D vBasePos = GGSM_FORMATION_GET_POSITION_FOR_DELAYED_LINE(group.sFormSettings, vSpreadDir, iFormIndex, spriteSize)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
group.fDistCounter = 0
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_HORZLINE(GGSM_ENTITY_GROUP &group)
|
|
INT i, ind
|
|
VECTOR_2D vDir = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
VECTOR_2D vStoredOrigin
|
|
VECTOR_2D vStartPos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
VECTOR_2D vBasePos = vStartPos
|
|
FLOAT fDist
|
|
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
FLOAT fDistBetweenUnits = ABSF(spriteSize.x) * spacing.x
|
|
FLOAT spd = entData.fBaseSpeed
|
|
|
|
fDist = 0
|
|
REPEAT group.sFormSettings.iFormationMembers i
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = vDir
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
|
|
vStoredOrigin = vStartPos
|
|
vStoredOrigin.x -= (vDir.x * fDist)
|
|
vStoredOrigin.y -= (vDir.y * fDist)
|
|
GGSM_ENTITY_SET_PACKED_ORIGIN(sGGSMData.sEntities[ind], vStoredOrigin)
|
|
|
|
fDist += fDistBetweenUnits
|
|
|
|
IF (vDir.x < 0)
|
|
vBasePos.x -= fDistBetweenUnits
|
|
ELSE
|
|
vBasePos.x += fDistBetweenUnits
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_VERTLINE(GGSM_ENTITY_GROUP &group)
|
|
INT i, ind
|
|
VECTOR_2D vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
|
|
FLOAT fDistBetweenUnits = ABSF(spriteSize.y) * spacing.y
|
|
FLOAT spd = entData.fBaseSpeed
|
|
|
|
vBasePos.y += (TO_FLOAT(group.iMembersToCreate) / 2.0) * fDistBetweenUnits
|
|
|
|
REPEAT group.sFormSettings.iFormationMembers i
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
|
|
vBasePos.y -= fDistBetweenUnits
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
group.iMembersToCreate = 0
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_FLYING_V(GGSM_ENTITY_GROUP &group)
|
|
INT i, ind
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
|
|
VECTOR_2D basePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
VECTOR_2D dir = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D transRootPos, checkPos
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
|
|
// move the group dist counter
|
|
group.fDistCounter += (entData.fBaseSpeed * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
transRootPos = basePos
|
|
GGSM_TRANSLATE_VECTOR_BY_DIRECTION(transRootPos, dir, group.fDistCounter)
|
|
|
|
REPEAT group.sFormSettings.iFormationMembers i
|
|
IF NOT IS_BIT_SET(group.iFormSpawnBitSet, i)
|
|
checkPos = GGSM_FORMATION_GET_POSITION_FOR_FLYING_V_EXPLICT(transRootPos, dir, i, spriteSize, spacing)
|
|
IF GGSM_IS_POINT_ON_SCREEN(checkPos, spriteSize)
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, checkPos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = dir
|
|
sGGSMData.sEntities[ind].fSpeed = entData.fBaseSpeed
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
|
|
SET_BIT(group.iFormSpawnBitSet, i)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_LINE(GGSM_ENTITY_GROUP &group)
|
|
INT i, ind
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
|
|
VECTOR_2D basePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
VECTOR_2D dir = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
VECTOR_2D transRootPos, checkPos
|
|
VECTOR_2D spacing = GGSM_FORMATION_GET_SPACING(group.sFormSettings)
|
|
|
|
// move the group dist counter
|
|
group.fDistCounter += (entData.fBaseSpeed * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
transRootPos = basePos
|
|
GGSM_TRANSLATE_VECTOR_BY_DIRECTION(transRootPos, dir, group.fDistCounter)
|
|
|
|
REPEAT group.sFormSettings.iFormationMembers i
|
|
IF NOT IS_BIT_SET(group.iFormSpawnBitSet, i)
|
|
checkPos = GGSM_FORMATION_GET_POSITION_FOR_LINE_EXPLICT(transRootPos, dir, i, spriteSize, spacing)
|
|
IF GGSM_IS_POINT_ON_SCREEN(checkPos, spriteSize)
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, checkPos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = dir
|
|
sGGSMData.sEntities[ind].fSpeed = entData.fBaseSpeed
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
|
|
SET_BIT(group.iFormSpawnBitSet, i)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_MIRROR_X(GGSM_ENTITY_GROUP &group)
|
|
INT i
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
FLOAT fDistBetweenUnits = FMAX(ABSF(spriteSize.x), ABSF(spriteSize.y)) * 1.5
|
|
FLOAT spd = entData.fBaseSpeed
|
|
VECTOR_2D dir
|
|
|
|
// move the dist counter so we can ensure the formation is reasonably spaced
|
|
group.fDistCounter += (spd * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
group.fDistCounter = CLAMP(group.fDistCounter, 0, fDistBetweenUnits)
|
|
IF (group.fDistCounter < fDistBetweenUnits)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT ind
|
|
VECTOR_2D vBasePos
|
|
|
|
// create leader
|
|
dir = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
|
|
REPEAT 2 i
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
IF (i = 1)
|
|
vBasePos.x = cfBASE_SCREEN_HALF_WIDTH - vBasePos.x
|
|
vBasePos.x += cfBASE_SCREEN_HALF_WIDTH
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = dir
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
IF (i = 1)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eMoveFlags, GGSM_MOVE_BIT_FLIP_RELATIVE_PATH_X)
|
|
ENDIF
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
group.fDistCounter = 0
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_MIRROR_Y(GGSM_ENTITY_GROUP &group)
|
|
INT i
|
|
GGSM_ENTITY_TYPE entType = GGSM_FORMATION_GET_ENTITY_TYPE(group.sFormSettings)
|
|
GGSM_ENTITY_DATA entData = GGSM_ENTITY_DATA_GET(entType)
|
|
VECTOR_2D spriteSize = GGSM_GET_SPRITE_SIZE(entData.eSpriteType)
|
|
FLOAT fDistBetweenUnits = FMAX(ABSF(spriteSize.x), ABSF(spriteSize.y)) * 1.5
|
|
FLOAT spd = entData.fBaseSpeed
|
|
VECTOR_2D dir
|
|
|
|
// move the dist counter so we can ensure the formation is reasonably spaced
|
|
group.fDistCounter += (spd * GET_FRAME_TIME() * sGGSMData.fTimeScale)
|
|
group.fDistCounter = CLAMP(group.fDistCounter, 0, fDistBetweenUnits)
|
|
IF (group.fDistCounter < fDistBetweenUnits)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT ind
|
|
VECTOR_2D vBasePos
|
|
|
|
// create leader
|
|
dir = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
|
|
REPEAT 2 i
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
IF (i = 1)
|
|
vBasePos.y = cfBASE_SCREEN_HALF_HEIGHT - vBasePos.y
|
|
vBasePos.y += cfBASE_SCREEN_HALF_HEIGHT
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], entType, vBasePos, 0)
|
|
sGGSMData.sEntities[ind].vLocalDirection = dir
|
|
sGGSMData.sEntities[ind].fSpeed = spd
|
|
|
|
IF (i = 1)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eMoveFlags, GGSM_MOVE_BIT_FLIP_RELATIVE_PATH_Y)
|
|
ENDIF
|
|
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
group.fDistCounter = 0
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_POWER_UP(GGSM_ENTITY_GROUP &group)
|
|
GGSM_SPRITE_TYPE eType = GGSM_FORMATION_GET_POWER_UP_SPRITE(group.sFormSettings)
|
|
IF (eType = GGSM_SPRITE_NONE)
|
|
group.iMembersToCreate = 0
|
|
EXIT
|
|
ENDIF
|
|
|
|
VECTOR_2D vPos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
IF NOT GGSM_CREATE_POWER_UP_AT(eType, vPos, sGGSMData.sPowerUp)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_DEACTIVATE_ENTITY_GROUP(group)
|
|
group.iMembersToCreate = 0
|
|
ENDPROC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE_FORMATION_BANANA_SNAKE(GGSM_ENTITY_GROUP &group)
|
|
INT iParent
|
|
INT iLeader, ind, count, i
|
|
VECTOR_2D vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
|
|
// create leader
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
EXIT
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_END_WHEN_ALL_OFFSCREEN | GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_BANANASLICE_FRONT, vBasePos)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_FORCE_SCROLLING_TO_STOP)
|
|
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[ind], 0)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[ind], group.sFormSettings)
|
|
|
|
// create segements
|
|
iLeader = ind
|
|
iParent = iLeader
|
|
count = group.sFormSettings.iFormationMembers - 2
|
|
|
|
REPEAT count i
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_BANANASLICE, INIT_VECTOR_2D(30.0, 0.0), 0, DEFAULT, iParent)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_SNAKE_SECTION)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[ind], i + 1)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
iParent = ind
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
// create tail
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_BANANASLICE_BACK, INIT_VECTOR_2D(30 + 10, 0.0), 0, DEFAULT, iParent)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_SNAKE_SECTION)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eMoveFlags, GGSM_MOVE_BIT_ROTATE_TO_FACE_DIRECTION)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[ind], group.sFormSettings.iFormationMembers)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
ENDIF
|
|
|
|
group.iMembersToCreate = 0
|
|
ENDPROC
|
|
|
|
FUNC BOOL GGSM_ENTITY_GROUP_UPDATE_FORMATION_ARMOURED_FRUITBOWL(GGSM_ENTITY_GROUP &group)
|
|
INT iLeaderIndex, ind, count, n
|
|
VECTOR_2D vBasePos = GGSM_FORMATION_GET_START_POSITION(group.sFormSettings)
|
|
GGSM_FORMATION_TYPE eFormType = GGSM_FORMATION_GET_TYPE(group.sFormSettings)
|
|
|
|
// create leader
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, iLeaderIndex, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_ALLOW_OFFSCREEN)
|
|
SET_BITMASK_ENUM_AS_ENUM(group.eFlags, GGSM_GROUP_BIT_DIE_WHEN_LEADER_DIES)
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[iLeaderIndex], GGSM_ENTITY_ARMOUR_FRUITBOWL, vBasePos)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeaderIndex].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeaderIndex].eFlags, GGSM_ENTITY_BIT_WPN_ACTIVE)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[iLeaderIndex].eFlags, GGSM_ENTITY_BIT_FORCE_SCROLLING_TO_STOP)
|
|
sGGSMData.sEntities[iLeaderIndex].vLocalDirection = GGSM_FORMATION_GET_START_DIRECTION(group.sFormSettings)
|
|
GGSM_ENTITY_SET_Z_DEPTH(sGGSMData.sEntities[iLeaderIndex], 0)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[iLeaderIndex], group.iGroupID)
|
|
GGSM_ENTITY_CONFIGURE_FROM_FORMATION(sGGSMData.sEntities[iLeaderIndex], group.sFormSettings)
|
|
sGGSMData.sEntities[iLeaderIndex].sLocal.vScale = INIT_VECTOR_2D(1.25, 1.25)
|
|
|
|
FLOAT ang
|
|
|
|
SWITCH (eFormType)
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL
|
|
DEFAULT
|
|
count = group.sFormSettings.iFormationMembers - 1
|
|
IF (count <= 0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (sGGSMData.bHardMode)
|
|
count += 2
|
|
ENDIF
|
|
ang = 360.0 / TO_FLOAT(count)
|
|
REPEAT count n
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_CIRCLE_SHIP_GREEN, INIT_VECTOR_2D(0, 0), 0, FALSE, iLeaderIndex)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_ORBIT, 150.0, (n * ang), 1.0)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_ENEMYSHOT_RAPID)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
sGGSMData.sEntities[ind].sLocal.vScale = INIT_VECTOR_2D(0.75, 0.75)
|
|
sGGSMData.sEntities[ind].iHP = 8
|
|
ENDIF
|
|
ENDREPEAT
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL1
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[iLeaderIndex], GGSM_WEAPON_ENEMYSPREAD)
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_CIRCLE_SHIP_YELLOW, INIT_VECTOR_2D(150, -150), 0, FALSE, iLeaderIndex)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_NONE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
sGGSMData.sEntities[ind].sLocal.vScale = INIT_VECTOR_2D(0.75, 0.75)
|
|
sGGSMData.sEntities[ind].iHP = 8
|
|
ENDIF
|
|
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_CIRCLE_SHIP_YELLOW, INIT_VECTOR_2D(150, 150), 0, FALSE, iLeaderIndex)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_NONE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_ENEMYSPREAD)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
sGGSMData.sEntities[ind].sLocal.vScale = INIT_VECTOR_2D(0.75, 0.75)
|
|
sGGSMData.sEntities[ind].iHP = 8
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL2
|
|
count = group.sFormSettings.iFormationMembers - 1
|
|
IF (count <= 0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
REPEAT count n
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_CIRCLE_SHIP_GREEN, INIT_VECTOR_2D(0, 0), 0, FALSE, iLeaderIndex)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_ORBIT, 150.0, (n * ang), 0.5)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_ENEMYSHOT)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
sGGSMData.sEntities[ind].sLocal.vScale = INIT_VECTOR_2D(0.75, 0.75)
|
|
sGGSMData.sEntities[ind].iHP = 4
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
n = 0
|
|
REPEAT count n
|
|
IF GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_CIRCLE_SHIP_GREEN, INIT_VECTOR_2D(0, 0), 0, FALSE, iLeaderIndex)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_ORBIT, 300.0, (n * ang), -0.5)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_ENEMYVULCAN)
|
|
CLEAR_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_WPN_TARGETTED)
|
|
GGSM_ADD_ENTITY_TO_GROUP(sGGSMData.sEntities[ind], group.iGroupID)
|
|
sGGSMData.sEntities[ind].sLocal.vScale = INIT_VECTOR_2D(0.75, 0.75)
|
|
sGGSMData.sEntities[ind].iHP = 4
|
|
ENDIF
|
|
ENDREPEAT
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC GGSM_ENTITY_GROUP_UPDATE(GGSM_ENTITY_GROUP &group)
|
|
IF (group.iMembersToCreate <= 0)
|
|
EXIT
|
|
ENDIF
|
|
|
|
INT iBossController
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(group.eFlags, GGSM_GROUP_BIT_ACTIVE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
sGGSMData.iGroupsActive ++
|
|
|
|
IF NOT IS_BITMASK_ENUM_AS_ENUM_SET(group.eFlags, GGSM_GROUP_BIT_IS_FORMATION)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_BITMASK_ENUM_AS_ENUM_SET(group.eFlags, GGSM_GROUP_BIT_IS_PLAYER_GROUP)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_FORMATION_TYPE eType = GGSM_FORMATION_GET_TYPE(group.sFormSettings)
|
|
|
|
SWITCH (eType)
|
|
CASE GGSM_FORMATION_STANDARD
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_STANDARD(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_FLYING_V
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_FLYING_V(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_LINE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_LINE(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_MIRROR_X
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_MIRROR_X(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_MIRROR_Y
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_MIRROR_Y(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_POWER_UP
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_POWER_UP(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_HORZLINE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_HORZLINE(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_VERTLINE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_VERTLINE(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_DELAYED_HLINE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_DELAYED_LINE(group, INIT_VECTOR_2D(1, 0))
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_DELAYED_VLINE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_DELAYED_LINE(group, INIT_VECTOR_2D(0, 1))
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BANANASNAKE
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_BANANA_SNAKE(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL1
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL2
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL3
|
|
CASE GGSM_FORMATION_ARMOUR_FRUITBOWL4
|
|
GGSM_ENTITY_GROUP_UPDATE_FORMATION_ARMOURED_FRUITBOWL(group)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BOSS_MARINE
|
|
iBossController = GGSM_GET_FREE_BOSS_CONTROLLER_INDEX(sGGSMData.sBossController)
|
|
IF (iBossController = GGSM_INVALID_BOSS_CONTROLLER)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
GGSM_RESET_BOSS_CONTROLLER(sGGSMData.sBossController[iBossController], GGSM_BOSS_MARINE)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BOSS_BREAD
|
|
iBossController = GGSM_GET_FREE_BOSS_CONTROLLER_INDEX(sGGSMData.sBossController)
|
|
IF (iBossController = GGSM_INVALID_BOSS_CONTROLLER)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
GGSM_RESET_BOSS_CONTROLLER(sGGSMData.sBossController[iBossController], GGSM_BOSS_BREAD)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BOSS_SMOOTHIE
|
|
iBossController = GGSM_GET_FREE_BOSS_CONTROLLER_INDEX(sGGSMData.sBossController)
|
|
IF (iBossController = GGSM_INVALID_BOSS_CONTROLLER)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
GGSM_RESET_BOSS_CONTROLLER(sGGSMData.sBossController[iBossController], GGSM_BOSS_SMOOTHIE)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BOSS_DR_DANK
|
|
iBossController = GGSM_GET_FREE_BOSS_CONTROLLER_INDEX(sGGSMData.sBossController)
|
|
IF (iBossController = GGSM_INVALID_BOSS_CONTROLLER)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
GGSM_RESET_BOSS_CONTROLLER(sGGSMData.sBossController[iBossController], GGSM_BOSS_DR_DANK)
|
|
BREAK
|
|
|
|
CASE GGSM_FORMATION_BOSS_GRANANA
|
|
iBossController = GGSM_GET_FREE_BOSS_CONTROLLER_INDEX(sGGSMData.sBossController)
|
|
IF (iBossController = GGSM_INVALID_BOSS_CONTROLLER)
|
|
EXIT
|
|
ENDIF
|
|
|
|
GGSM_RESET_ENTITY_GROUP(group)
|
|
GGSM_RESET_BOSS_CONTROLLER(sGGSMData.sBossController[iBossController], GGSM_BOSS_GRANANA)
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
|
|
//-------------------------------------------------
|
|
// SPECIAL INIT FUNCTIONS
|
|
//-------------------------------------------------
|
|
FUNC BOOL GGSM_PLAYER_SHIP_INIT(VECTOR_2D vLocalPos)
|
|
INT ind
|
|
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_PLAYERSHIP, vLocalPos, DEFAULT, TRUE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_PLAYER_CONTROLLED)
|
|
//GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_PLYRBACKVULCAN)
|
|
|
|
sGGSMData.iPlayerShipIndex = ind
|
|
sGGSMData.fKillStreakTimer = 0.0
|
|
sGGSMData.iKillStreak = 0
|
|
sGGSMData.bGrazed = FALSE
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_PLAYER_DECOY_INIT(VECTOR_2D vLocalPos)
|
|
INT ind
|
|
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_PLAYERDECOY, vLocalPos, DEFAULT, TRUE)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_NONE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_NONE)
|
|
sGGSMData.sEntities[ind].iPackedColor = GGSM_PACK_RGBA_COLOUR(0, 255, 0, 128)
|
|
|
|
sGGSMData.iPlayerDecoyIndex = ind
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL GGSM_PLAYER_SHIELD_INIT(BOOL bReflectShield = FALSE)
|
|
INT ind
|
|
|
|
IF GGSM_DOES_PLAYER_SHIELD_EXIST()
|
|
GGSM_ENTITY_DESTROY(sGGSMData.sEntities[sGGSMData.iPlayerShieldIndex])
|
|
ENDIF
|
|
|
|
IF NOT GGSM_GET_FREE_ENTITY(sGGSMData.sEntities, ind, sGGSMData.iEntitySearchIndex)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_INIT(sGGSMData.sEntities[ind], GGSM_ENTITY_PLAYERSHIELD, INIT_VECTOR_2D(0, 0), DEFAULT, TRUE, sGGSMData.iPlayerShipIndex)
|
|
GGSM_ENTITY_SET_WEAPON(sGGSMData.sEntities[ind], GGSM_WEAPON_NONE)
|
|
GGSM_ENTITY_SET_MOVEMENT_TYPE(sGGSMData.sEntities[ind], GGSM_MOVEMENT_NONE)
|
|
|
|
IF (bReflectShield)
|
|
SET_BITMASK_ENUM_AS_ENUM(sGGSMData.sEntities[ind].eFlags, GGSM_ENTITY_BIT_REFLECT_BULLETS)
|
|
sGGSMData.sEntities[ind].iPackedColor = GGSM_PACK_RGBA_COLOUR(0, 255, 0, 255)
|
|
ELSE
|
|
sGGSMData.sEntities[ind].iPackedColor = GGSM_PACK_RGBA_COLOUR(0, 0, 255, 255)
|
|
ENDIF
|
|
|
|
sGGSMData.iPlayerShieldIndex = ind
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC FLOAT GGSM_GET_PLAYER_SHIP_HP_PERCENTAGE()
|
|
IF NOT GGSM_DOES_PLAYER_SHIP_EXIST()
|
|
RETURN 0.0
|
|
ENDIF
|
|
|
|
GGSM_ENTITY_DATA dat = GGSM_ENTITY_DATA_GET(sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].eType)
|
|
RETURN TO_FLOAT(sGGSMData.sEntities[sGGSMData.iPlayerShipIndex].iHP) / TO_FLOAT(dat.iMaxHP)
|
|
ENDFUNC
|
|
|
|
|
|
|
|
|