123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- class Watchtower extends BaseBuildingBase
- {
- typename ATTACHMENT_BARBED_WIRE = BarbedWire;
- typename ATTACHMENT_CAMONET = CamoNet;
-
- const float MAX_FLOOR_VERTICAL_DISTANCE = 0.5;
-
- const float MIN_ACTION_DETECTION_ANGLE_RAD = 0.35; //0.35 RAD = 20 DEG
- const float MAX_ACTION_DETECTION_DISTANCE = 2.0; //meters
-
- static const string BASE_VIEW_NAME = "level_";
- static const string BASE_WALL_NAME = "_wall_";
- static const string BASE_ROOF_NAME = "_roof";
- static const int MAX_WATCHTOWER_FLOORS = 3;
- static const int MAX_WATCHTOWER_WALLS = 3;
-
- void Watchtower()
- {
- }
-
- override string GetConstructionKitType()
- {
- return "WatchtowerKit";
- }
-
- override int GetMeleeTargetType()
- {
- return EMeleeTargetType.NONALIGNABLE;
- }
-
- /*override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
- {
- super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
-
- if (component == -1)
- {
- Print("EEHitBy: " + this + "; damageType: "+ damageType +"; source: "+ source +"; component: "+ component +"; dmgZone: "+ dmgZone +"; ammo: "+ ammo +"; modelPos: "+ modelPos);
- Print("GetDamage " + damageResult.GetDamage("","Health"));
- Print("GetHighestDamage " + damageResult.GetHighestDamage("Health"));
- }
- }*/
-
- //overriden for the express purpose of handling view geometry (interaction) animations
- override void UpdateVisuals()
- {
- super.UpdateVisuals();
-
- SetAnimationPhase( "level_1", 0); //always visible
- SetAnimationPhase( "level_1_wall_1", 0); //always visible
- SetAnimationPhase( "level_1_wall_2", 0); //always visible
- SetAnimationPhase( "level_1_wall_3", 0); //always visible
-
- string part_name = "";
- bool built = false;
-
- for ( int i = 1; i < MAX_WATCHTOWER_FLOORS; ++i )
- {
- //roof checks
- part_name = "" + BASE_VIEW_NAME + i + BASE_ROOF_NAME;
- built = GetConstruction().IsPartConstructed(part_name);
- //Print(part_name);
- //Print(built);
-
- //string tmp = "";
-
- if ( built )
- {
- SetAnimationPhase( BASE_VIEW_NAME + (i + 1), 0); //show
- for ( int j = 1; j < MAX_WATCHTOWER_WALLS + 1; ++j )
- {
- //tmp = BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j;
- //Print(tmp);
- SetAnimationPhase( BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j, 0); //show
- }
- }
- else
- {
- SetAnimationPhase( BASE_VIEW_NAME + (i + 1), 1 ); //hide
- for ( j = 1; j < MAX_WATCHTOWER_WALLS + 1; ++j )
- {
- //tmp = BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j;
- //Print(tmp);
- SetAnimationPhase( BASE_VIEW_NAME + (i + 1) + BASE_WALL_NAME + j, 1); //hide
- }
- }
- }
- }
-
- //--- ATTACHMENT & CONDITIONS
- override bool CanReceiveAttachment( EntityAI attachment, int slotId )
- {
- if ( !super.CanReceiveAttachment( attachment, slotId ) )
- return false;
- //because CanReceiveAttachment() method can be called on all clients in the vicinity, vertical distance check needs to be skipped on clients that don't
- //interact with the object through attach action (AT_ATTACH_TO_CONSTRUCTION)
- PlayerBase player;
- if ( !GetGame().IsDedicatedServer() )
- {
- //check action initiator (AT_ATTACH_TO_CONSTRUCTION)
- player = PlayerBase.Cast( GetGame().GetPlayer() );
- if ( player )
- {
- ConstructionActionData construction_action_data = player.GetConstructionActionData();
- PlayerBase action_initiator = construction_action_data.GetActionInitiator();
-
- if ( action_initiator == player )
- {
- construction_action_data.SetActionInitiator( NULL ); //reset action initiator
- }
- else
- {
- player = null; //do not do vertical check (next)
- }
- }
- }
- //
-
- return CheckSlotVerticalDistance( slotId, player );
- }
-
- //can put into hands
- override bool CanPutIntoHands( EntityAI parent )
- {
- return false;
- }
-
- override bool CanBeRepairedToPristine()
- {
- return true;
- }
-
- override bool PerformRoofCheckForBase( string partName, PlayerBase player, out bool result )
- {
- if (CfgGameplayHandler.GetDisablePerformRoofCheck())
- return false;
-
- if (partName != "level_1_base" && partName != "level_2_base" && partName != "level_3_base" && partName != "level_3_roof")
- {
- return false;
- }
-
- vector center;
- vector orientation = GetOrientation();
- vector edge_length;
- vector min_max[2];
- ref array<Object> excluded_objects = new array<Object>;
- ref array<Object> collided_objects = new array<Object>;
-
- excluded_objects.Insert( this );
- excluded_objects.Insert( player );
-
- if ( partName == "level_2_base" )
- {
- min_max[0] = GetMemoryPointPos( "level_2_wall_1_down_min" );
- min_max[1] = GetMemoryPointPos( "level_2_roof_max" );
- }
- else if ( partName == "level_3_base" )
- {
- min_max[0] = GetMemoryPointPos( "level_3_wall_1_down_min" );
- min_max[1] = GetMemoryPointPos( "level_3_wall_2_up_max" );
- }
- else if ( partName == "level_3_roof" )
- {
- min_max[0] = GetMemoryPointPos( "level_3_roof_min" );
- min_max[1] = GetMemoryPointPos( "level_3_roof_max" );
- }
- else
- {
- //min_max[0] = GetMemoryPointPos( "level_1_wall_1_up_min" );
- //min_max[0] = GetMemoryPointPos( "level_1_wall_1_down_min" );
- min_max[0] = GetMemoryPointPos( "level_1_collisioncheck_min" );
- min_max[1] = GetMemoryPointPos( "level_1_roof_max" );
- }
- center = GetPosition();
- center[1] = center[1] + ( min_max[1][1] + min_max[0][1] ) / 2;
-
- edge_length[0] = min_max[1][0] - min_max[0][0];
- edge_length[2] = min_max[1][2] - min_max[0][2];
- edge_length[1] = min_max[1][1] - min_max[0][1];
-
- result = false;
- /*result = */GetGame().IsBoxCollidingGeometry( center, orientation, edge_length, ObjIntersectView, ObjIntersectGeom, excluded_objects, collided_objects );
- if ( collided_objects.Count() > 0 )
- {
- foreach ( Object o : collided_objects )
- {
- if (Building.Cast(o))
- {
- result = true;
- }
- }
- }
- return true;
- }
-
- // --- INVENTORY
- override bool CanDisplayAttachmentSlot( int slot_id )
- {
- //super
- if ( !super.CanDisplayAttachmentSlot( slot_id ) )
- return false;
- string slot_name = InventorySlots.GetSlotName(slot_id);
- slot_name.ToLower();
- PlayerBase player = PlayerBase.Cast( GetGame().GetPlayer() );
- //base attachments
- if ( slot_name.Contains( "material_l1" ) || slot_name.Contains( "level_1_" ) )
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_1_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- }
- else if ( slot_name.Contains( "material_l2" ) || slot_name.Contains( "level_2_" ) )
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_2_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- }
- else if ( slot_name.Contains( "material_l3" ) || slot_name.Contains( "level_3_" ) )
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_3_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- }
-
- return true;
- }
- override bool CanDisplayAttachmentCategory( string category_name )
- {
- //super
- if ( !super.CanDisplayAttachmentCategory( category_name ) )
- return false;
- //
-
- category_name.ToLower();
- PlayerBase player = PlayerBase.Cast( GetGame().GetPlayer() );
- //level 1
- if ( category_name.Contains( "level_1" ) )
- {
- if ( category_name.Contains( "level_1_" ) )
- {
- return GetConstruction().IsPartConstructed( "level_1_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- else
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- }
- //level 2
- if ( category_name.Contains( "level_2" ) )
- {
- if ( category_name.Contains( "level_2_" ) )
- {
- return GetConstruction().IsPartConstructed( "level_2_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_1_roof" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- }
- //level 3
- if ( category_name.Contains( "level_3" ) )
- {
- if ( category_name.Contains( "level_3_" ) )
- {
- return GetConstruction().IsPartConstructed( "level_3_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_2_roof" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- }
-
- return true;
- }
-
- //returns true if attachment slot position is within given range
- override bool CheckSlotVerticalDistance( int slot_id, PlayerBase player )
- {
- string slot_name;
- InventorySlots.GetSelectionForSlotId( slot_id , slot_name );
- slot_name.ToLower();
-
- //wall attachments
- //level 1
- if ( slot_name.Contains( "material_l1" ) || slot_name.Contains( "level_1_" ) )
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_1_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_1", player );
- }
- }
- //level 2
- if ( slot_name.Contains( "material_l2" ) || slot_name.Contains( "level_2_" ) )
- {
- if ( slot_name.Contains( "material_l2w" ) || slot_name.Contains( "level_2_wall" ) )
- {
- return GetConstruction().IsPartConstructed( "level_2_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- else
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_1_roof" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_2", player );
- }
- }
- }
- //level 3
- if ( slot_name.Contains( "material_l3" ) || slot_name.Contains( "level_3_" ) )
- {
- if ( slot_name.Contains( "material_l3w" ) || slot_name.Contains( "level_3_wall" ) )
- {
- return GetConstruction().IsPartConstructed( "level_3_base" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- else
- {
- if ( slot_name.Contains( "woodenlogs" ) )
- {
- return CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- else
- {
- return GetConstruction().IsPartConstructed( "level_2_roof" ) && CheckMemoryPointVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, "level_3", player );
- }
- }
- }
-
- return true;
- }
-
- //returns true if player->mem_point position is within given range
- override bool CheckMemoryPointVerticalDistance( float max_dist, string selection, PlayerBase player )
- {
- if ( player )
- {
- //check vertical distance
- vector player_pos = player.GetPosition();
- vector pos;
-
- if ( MemoryPointExists( selection ) )
- {
- pos = ModelToWorld( GetMemoryPointPos( selection ) );
- }
-
- if ( Math.AbsFloat( player_pos[1] - pos[1] ) <= max_dist )
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- return true;
- }
-
- override bool CheckLevelVerticalDistance( float max_dist, string selection, PlayerBase player )
- {
- if ( player )
- {
- if ( selection.Contains( "level_1_" ) )
- return CheckMemoryPointVerticalDistance( max_dist, "level_1", player );
-
- if ( selection.Contains( "level_2_" ) )
- return CheckMemoryPointVerticalDistance( max_dist, "level_2", player );
-
- if ( selection.Contains( "level_3_" ) )
- return CheckMemoryPointVerticalDistance( max_dist, "level_3", player );
- }
- return false;
- }
- // ---
- override void AfterStoreLoad()
- {
- super.AfterStoreLoad();
-
- UpdateVisuals();
- }
-
- override void OnPartBuiltServer( notnull Man player, string part_name, int action_id )
- {
- super.OnPartBuiltServer( player, part_name, action_id );
- //update visuals (server)
- UpdateVisuals();
- }
-
- override void OnPartDismantledServer( notnull Man player, string part_name, int action_id )
- {
- super.OnPartDismantledServer( player, part_name, action_id );
- //update visuals (server)
- UpdateVisuals();
- }
-
- override void OnPartDestroyedServer( Man player, string part_name, int action_id, bool destroyed_by_connected_part = false )
- {
- super.OnPartDestroyedServer( player, part_name, action_id );
- //update visuals (server)
- UpdateVisuals();
- }
-
- //--- ACTION CONDITIONS
- //returns dot product of player->construction direction based on existing/non-existing reference point
- override bool IsFacingPlayer( PlayerBase player, string selection )
- {
- vector ref_pos;
- vector ref_dir;
- vector player_dir;
- float dot;
- bool has_memory_point = MemoryPointExists( selection );
-
- if ( has_memory_point )
- {
- ref_pos = ModelToWorld( GetMemoryPointPos( selection ) );
- ref_dir = ref_pos - GetPosition();
- }
- else
- {
- ref_pos = GetPosition();
- ref_dir = ref_pos - player.GetPosition();
- }
-
- ref_dir.Normalize();
- ref_dir[1] = 0; //ignore height
-
- player_dir = player.GetDirection();
- player_dir.Normalize();
- player_dir[1] = 0; //ignore height
-
- if ( ref_dir.Length() != 0 )
- {
- dot = vector.Dot( player_dir, ref_dir );
- }
-
- if ( has_memory_point )
- {
- if ( dot < 0 && Math.AbsFloat( dot ) > MIN_ACTION_DETECTION_ANGLE_RAD )
- {
- return true;
- }
- }
- else
- {
- if ( dot > 0 && Math.AbsFloat( dot ) > MIN_ACTION_DETECTION_ANGLE_RAD )
- {
- return true;
- }
- }
-
- return false;
- }
-
- override bool IsFacingCamera( string selection )
- {
- vector ref_pos;
- vector ref_dir;
- vector cam_dir = GetGame().GetCurrentCameraDirection();
-
- if ( MemoryPointExists( selection ) )
- {
- ref_pos = ModelToWorld( GetMemoryPointPos( selection ) );
- ref_dir = ref_pos - GetPosition();
-
- ref_dir.Normalize();
- ref_dir[1] = 0; //ignore height
-
- cam_dir[1] = 0; //ignore height
-
- if ( ref_dir.Length() > 0.5 ) //if the distance (m) is too low, ignore this check
- {
- float dot = vector.Dot( cam_dir, ref_dir );
-
- if ( dot < 0 )
- {
- return true;
- }
- }
- }
- return false;
- }
-
- override bool IsPlayerInside( PlayerBase player, string selection )
- {
- if ( selection != "")
- {
- CheckLevelVerticalDistance( MAX_FLOOR_VERTICAL_DISTANCE, selection, player );
- }
- vector player_pos = player.GetPosition();
- vector tower_pos = GetPosition();
- vector ref_dir = GetDirection();
- ref_dir[1] = 0;
- ref_dir.Normalize();
-
- vector min,max;
-
- min = -GetMemoryPointPos( "interact_min" );
- max = -GetMemoryPointPos( "interact_max" );
-
- vector dir_to_tower = tower_pos - player_pos;
- dir_to_tower[1] = 0;
- float len = dir_to_tower.Length();
-
- dir_to_tower.Normalize();
-
- vector ref_dir_angle = ref_dir.VectorToAngles();
- vector dir_to_tower_angle = dir_to_tower.VectorToAngles();
- vector test_angles = dir_to_tower_angle - ref_dir_angle;
-
- vector test_position = test_angles.AnglesToVector() * len;
-
- if (test_position[0] > max[0] || test_position[0] < min[0] || test_position[2] > max[2] || test_position[2] < min[2] )
- {
- return false;
- }
- return true;
- }
-
- override bool HasProperDistance( string selection, PlayerBase player )
- {
- if ( MemoryPointExists( selection ) )
- {
- vector selection_pos = ModelToWorld( GetMemoryPointPos( selection ) );
- float distance = vector.Distance( selection_pos, player.GetPosition() );
- if ( distance >= MAX_ACTION_DETECTION_DISTANCE )
- {
- return false;
- }
- }
-
- return true;
- }
-
- override void SetActions()
- {
- super.SetActions();
-
- AddAction(ActionTogglePlaceObject);
- AddAction(ActionPlaceObject);
- AddAction(ActionFoldBaseBuildingObject);
- }
-
-
- //================================================================
- // DEBUG
- //================================================================
-
- //! Excludes certain parts from being built by OnDebugSpawn, uses Contains to compare
- override array<string> OnDebugSpawnBuildExcludes()
- {
- array<string> excludes;
-
- #ifdef DIAG_DEVELOPER
- bool bWood = DiagMenu.GetBool(DiagMenuIDs.BASEBUILDING_WOOD);
- #else
- bool bWood = false;
- #endif
-
- if (bWood)
- {
- excludes = {"_metal_"};
- }
- else
- {
- excludes = {"_wood_"};
- }
-
- return excludes;
- }
-
- //Debug menu Spawn Ground Special
- override void OnDebugSpawn()
- {
- super.OnDebugSpawn();
-
- int i;
-
- for (i = 0; i < MAX_WATCHTOWER_FLOORS * MAX_WATCHTOWER_WALLS; ++i)
- {
- GetInventory().CreateInInventory("CamoNet");
- }
-
- for (i = 0; i < 2 * MAX_WATCHTOWER_WALLS; ++i)
- {
- BarbedWire wire = BarbedWire.Cast(GetInventory().CreateInInventory("BarbedWire"));
- wire.SetMountedState(true);
- }
- }
- }
|