4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Graphics;
17 private float shakeTimer;
18 private Vector2 shakePos;
21 private float lastConvexHullState;
23 [Serialize(
"1,1",
IsPropertySaveable.No, description:
"The scale of the shadow-casting area of the door (relative to the actual size of the door).")]
33 get {
return Vector2.Zero; }
36 private Vector2[] GetConvexHullCorners(Rectangle rect)
39 Vector2 center =
new Vector2(rect.Center.X, rect.Y - rect.Height / 2);
41 Vector2[] corners =
new Vector2[4];
42 corners[0] = center +
new Vector2(-shadowSize.X, -shadowSize.Y) / 2;
43 corners[1] = center +
new Vector2(-shadowSize.X, shadowSize.Y) / 2;
44 corners[2] = center +
new Vector2(shadowSize.X, shadowSize.Y) / 2;
45 corners[3] = center +
new Vector2(shadowSize.X, -shadowSize.Y) / 2;
52 for (
int i = 0; i < corners.Length; i++)
54 corners[i].X = itemCenter.X * 2 - corners[i].X;
56 Array.Reverse(corners);
64 for (
int i = 0; i < corners.Length; i++)
66 corners[i].Y = itemCenter.Y * 2 - corners[i].Y;
68 Array.Reverse(corners);
75 private void UpdateConvexHulls()
78 if (doorSprite ==
null) {
return; }
89 rect.Width = (int)(rect.Width * (1.0f - openState));
93 rect.Height = (int)(rect.Height * (1.0f - openState));
101 rect.X -= (int)(doorRect.Width * openState);
102 rect.Width = Math.Max(rect.Width - (doorRect.X - rect.X), 0);
103 rect.X = Math.Max(doorRect.X, rect.X);
104 if (convexHull2 !=
null)
108 rect2.X -= (int)(doorRect.Width * openState);
109 rect2.X = Math.Max(doorRect.X, rect2.X);
110 rect2.Width = doorRect.Right - (int)(doorRect.Width * openState) - rect2.X;
111 if (rect2.Width == 0)
118 SetVertices(convexHull2, rect2);
125 rect.Y += (int)(doorRect.Height * openState);
126 rect.Height = Math.Max(rect.Height - (rect.Y - doorRect.Y), 0);
127 rect.Y = Math.Min(doorRect.Y, rect.Y);
128 if (convexHull2 !=
null)
132 rect2.Y += (int)(doorRect.Height * openState);
133 rect2.Y = Math.Min(doorRect.Y, rect2.Y);
134 rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
135 if (rect2.Height == 0)
142 SetVertices(convexHull2, rect2);
148 if (convexHull ==
null) {
return; }
150 if (rect.Height == 0 || rect.Width == 0)
157 SetVertices(convexHull, rect);
162 private void SetVertices(
ConvexHull convexHull, Rectangle rect)
164 var verts = GetConvexHullCorners(rect);
165 Vector2 center = (verts[0] + verts[2]) / 2;
169 new Vector2[] {
new Vector2(verts[0].X, center.Y),
new Vector2(verts[2].X, center.Y) } :
170 new Vector2[] {
new Vector2(center.X, verts[0].Y),
new Vector2(center.X, verts[2].Y) });
174 partial
void UpdateProjSpecific(
float deltaTime)
176 if (shakeTimer > 0.0f)
178 shakeTimer -= deltaTime;
179 Vector2 noisePos =
new Vector2((
float)PerlinNoise.CalculatePerlin(shakeTimer * 10.0f, shakeTimer * 10.0f, 0) - 0.5f, (
float)PerlinNoise.CalculatePerlin(shakeTimer * 10.0f, shakeTimer * 10.0f, 0.5f) - 0.5f);
180 shakePos = noisePos * shake * 2.0f;
181 shake = Math.Min(shake, shakeTimer * 10.0f);
185 shakePos = Vector2.Zero;
189 public void Draw(SpriteBatch spriteBatch,
bool editing,
float itemDepth = -1, Color? overrideColor =
null)
192 if (brokenSprite ==
null)
199 if (stuck > 0.0f && weldedSprite !=
null)
203 weldSpritePos.Y = -weldSpritePos.Y;
205 weldedSprite.
Draw(spriteBatch,
209 if (openState >= 1.0f) {
return; }
227 if (brokenSprite ==
null || !
IsBroken)
229 if (doorSprite?.Texture !=
null)
231 spriteBatch.Draw(doorSprite.
Texture, pos,
240 float healthRatio =
item.
Health / maxCondition;
241 if (brokenSprite?.Texture !=
null && healthRatio < 1.0f)
243 Vector2 scale = scaleBrokenSprite ?
new Vector2(1.0f - healthRatio) : Vector2.One;
244 if (
IsHorizontal) { scale.X = 1; }
else { scale.Y = 1; }
245 float alpha = fadeBrokenSprite ? 1.0f - healthRatio : 1.0f;
246 spriteBatch.Draw(brokenSprite.
Texture, pos,
252 static Rectangle getSourceRect(
Sprite sprite,
float openState,
bool horizontal)
259 (
int)(sprite.
size.X * (1.0f - openState)),
268 (
int)(sprite.
size.Y * (1.0f - openState)));
273 partial
void OnFailedToOpen()
275 if (shakeTimer <= 0.0f)
283 partial
void SetState(
bool open,
bool isNetworkMessage,
bool sendNetworkMessage,
bool forcedOpen)
285 if ((
IsStuck && !isNetworkMessage) ||
292 if (GameMain.Client !=
null && !isNetworkMessage)
303 PlayInteractionSound();
308 bool stateChanged = open != isOpen;
315 PlayInteractionSound();
317 if (isOpen) { stuck = MathHelper.Clamp(stuck - StuckReductionOnOpen, 0.0f, 100.0f); }
326 void PlayInteractionSound()
350 base.ClientEventRead(msg, sendingTime);
357 SetState(open, isNetworkMessage:
true, sendNetworkMessage:
false, forcedOpen: forcedOpen);
361 if (user != lastUser)
366 this.isStuck = isStuck;
367 this.isJammed = isJammed;
static Entity FindEntityByID(ushort ID)
Find an entity based on the ID
void ApplyStatusEffects(ActionType type, float deltaTime, Character character=null, Limb limb=null, Entity useTarget=null, bool isNetworkEvent=false, Vector2? worldPosition=null)
Executes all StatusEffects of the specified type. Note that condition checks are ignored here: that s...
Color GetSpriteColor(Color? defaultColor=null, bool withHighlight=false)
List< Repairable > Repairables
SpriteEffects SpriteEffects
override void ClientEventRead(IReadMessage msg, float sendingTime)
void Draw(SpriteBatch spriteBatch, bool editing, float itemDepth=-1, Color? overrideColor=null)
bool IsConvexHullHorizontal
const float CorrectionDelay
void PlaySound(ActionType type, Character user=null)
void StopPicking(Character picker)
void SetVertices(Vector2[] points, Vector2[] losPoints, bool mergeOverlappingSegments=true, Matrix? rotationMatrix=null)
float? MaxMergeLosVerticesDist
Overrides the maximum distance a LOS vertex can be moved to make it align with a nearby LOS segment
void Draw(ISpriteBatch spriteBatch, Vector2 pos, float rotate=0.0f, float scale=1.0f, SpriteEffects spriteEffect=SpriteEffects.None)
Single ReadRangedSingle(Single min, Single max, int bitCount)
Interface for entities that the server can send events to the clients
ActionType
ActionTypes define when a StatusEffect is executed.