· 7 years ago · Oct 22, 2018, 07:08 AM
1if SERVER then
2 AddCSLuaFile( )
3end
4
5if (CLIENT) then
6 SWEP.PrintName = "Бинокль"
7 SWEP.Author = "McVipeR"
8 SWEP.Contact = ""
9 SWEP.Instructions = "ЛКМ - чтобы поÑмотреть в бинокль\nПКМ - чтобы наÑтроить зум"
10 SWEP.Slot = 0
11 SWEP.SlotPos = 8
12 SWEP.ViewModelFOV = 45
13 SWEP.ViewModelFlip = false
14 SWEP.BounceWeaponIcon = false
15end
16
17SWEP.Base = "weapon_base"
18SWEP.HoldType = "normal"
19
20SWEP.Category = "StalkerRP Sweps"
21SWEP.Spawnable = true
22SWEP.AdminOnly = false
23
24SWEP.ShowWorldModel = false
25
26SWEP.ViewModel = "models/weapons/stalker/v_binoculars.mdl"
27SWEP.WorldModel = "models/bin.mdl"
28
29SWEP.IronSightsPos = Vector( -4.5, -38, 10 )
30SWEP.IronSightsAng = Vector( 0, 14, 0 )
31
32SWEP.Primary.ClipSize = -1
33SWEP.Primary.DefaultClip = -1
34SWEP.Primary.Ammo = "none"
35
36SWEP.Secondary.ClipSize = -1
37SWEP.Secondary.DefaultClip = -1
38SWEP.Secondary.Ammo = "none"
39
40SWEP.BinZoom = 10
41
42SWEP.WElements = {
43 ["bin"] = { type = "Model", model = "models/bin.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(0, 0, -1), angle = Angle(0, 0, 190), size = Vector(1.0, 1.0, 1.0), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} }
44}
45
46
47local IRONSIGHT_TIME = 0.5
48function SWEP:GetViewModelPosition( pos, ang )
49
50 if ( !self.IronSightsPos ) then return pos, ang end
51
52 local bIron = self.Weapon:GetNetworkedBool( "Ironsights" )
53
54 if ( bIron != self.bLastIron ) then
55
56 self.bLastIron = bIron
57 self.fIronTime = CurTime()
58
59 if ( bIron ) then
60 self.SwayScale = 0.3
61 self.BobScale = 0.1
62 else
63 self.SwayScale = 1.0
64 self.BobScale = 1.0
65 end
66
67 end
68
69 local fIronTime = self.fIronTime or 0
70
71 if ( !bIron && fIronTime < CurTime() - IRONSIGHT_TIME ) then
72 return pos, ang
73 end
74
75 local Mul = 1.0
76
77 if ( fIronTime > CurTime() - IRONSIGHT_TIME ) then
78
79 Mul = math.Clamp( (CurTime() - fIronTime) / IRONSIGHT_TIME, 0, 1 )
80
81 if (!bIron) then Mul = 1 - Mul end
82
83 end
84
85 local Offset = self.IronSightsPos
86
87 if ( self.IronSightsAng ) then
88
89 ang = ang * 1
90 ang:RotateAroundAxis( ang:Right(), self.IronSightsAng.x * Mul )
91 ang:RotateAroundAxis( ang:Up(), self.IronSightsAng.y * Mul )
92 ang:RotateAroundAxis( ang:Forward(), self.IronSightsAng.z * Mul )
93
94
95 end
96
97 local Right = ang:Right()
98 local Up = ang:Up()
99 local Forward = ang:Forward()
100
101
102
103 pos = pos + Offset.x * Right * Mul
104 pos = pos + Offset.y * Forward * Mul
105 pos = pos + Offset.z * Up * Mul
106
107 return pos, ang
108
109end
110
111function SWEP:Initialize()
112
113 self:SetHoldType( self.HoldType )
114
115 if CLIENT then
116
117 self.VElements = table.FullCopy( self.VElements )
118 self.WElements = table.FullCopy( self.WElements )
119 self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods )
120
121 self:CreateModels(self.VElements) // create viewmodels
122 self:CreateModels(self.WElements) // create worldmodels
123
124 self:SetNetworkedBool( "Ironsights", false )
125
126 if IsValid(self.Owner) then
127 local vm = self.Owner:GetViewModel()
128 if IsValid(vm) then
129 self:ResetBonePositions(vm)
130
131 end
132 end
133
134 end
135end
136
137function SWEP:SetZoom(state)
138 if CLIENT then
139 return
140 elseif IsValid(self.Owner) and self.Owner:IsPlayer() then
141 if state then
142 self.Owner:EmitSound("weapons/stalker/binoculars_zoomin.wav", 30, 100)
143 self:SetHoldType( "camera" )
144 self.Owner:DrawViewModel(false)
145 self.Owner:SetFOV(self.BinZoom, 0.5)
146 else
147 self.Owner:EmitSound("weapons/stalker/binoculars_zoomout.wav", 30, 100)
148 self:SetHoldType( self.HoldType )
149 self.Owner:SetFOV(0, 0.2)
150 self.Owner:DrawViewModel(true)
151 end
152 end
153end
154
155function SWEP:SecondaryAttack()
156
157 self.Weapon:SetNextSecondaryFire(CurTime() + 0.5)
158
159 if self.BinZoom == 0.8 then
160
161 if (SERVER) then
162 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 5 X.")
163 end
164
165 self.BinZoom = 1.5
166
167 elseif self.BinZoom == 1.5 then
168
169 if (SERVER) then
170 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 4 X.")
171 end
172
173 self.BinZoom = 3
174
175 elseif self.BinZoom == 3 then
176 if (SERVER) then
177
178 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 3 X.")
179 end
180
181 self.BinZoom = 6
182
183 elseif self.BinZoom == 6 then
184
185 if (SERVER) then
186 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 2 X.")
187 end
188
189 self.BinZoom = 8
190
191 elseif self.BinZoom == 8 then
192
193 if (SERVER) then
194 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 1 X.")
195 end
196
197 self.BinZoom = 10
198
199 elseif self.BinZoom == 10 then
200
201 if (SERVER) then
202 self.Owner:PrintMessage(HUD_PRINTTALK, "Приближение: 6 X.")
203 end
204
205 self.BinZoom = 0.8
206
207 end
208
209end
210
211function SWEP:PrimaryAttack()
212 if not self.IronSightsPos then return end
213 if self:GetNextSecondaryFire() > CurTime() then return end
214
215 bIronsights = not self.Weapon:GetNWBool("Ironsights")
216 self.Weapon:SetNetworkedBool("Ironsights", bIronsights)
217
218 if SERVER then
219 self:SetZoom(bIronsights)
220 end
221
222 self:SetNextSecondaryFire(CurTime() + 0.3)
223end
224
225function SWEP:Holster()
226
227 self.Weapon:SetNetworkedBool("Ironsights", false)
228 self:SetZoom(false)
229
230 if CLIENT and IsValid(self.Owner) then
231 local vm = self.Owner:GetViewModel()
232 if IsValid(vm) then
233 self:ResetBonePositions(vm)
234 end
235 end
236
237 return true
238end
239
240if CLIENT then
241 local scope = surface.GetTextureID("models/weapons/stalker/wpn_crosshair_bino")
242 function SWEP:DrawHUD()
243
244 if self.Weapon:GetNWBool("Ironsights") then
245
246 self.DrawCrosshair = false
247 surface.SetDrawColor( 0, 0, 0, 255 )
248
249 local x = ScrW() / 2.0
250 local y = ScrH() / 2.0
251 local scope_size = ScrH()
252
253 -- crosshair
254 local gap = 80
255 local length = scope_size
256 surface.DrawLine(x - length, y, x - gap, y)
257 surface.DrawLine(x + length, y, x + gap, y)
258 surface.DrawLine(x, y - length, x, y - gap)
259 surface.DrawLine(x, y + length, x, y + gap)
260
261 gap = 0
262 length = 50
263 surface.DrawLine(x - length, y, x - gap, y)
264 surface.DrawLine(x + length, y, x + gap, y)
265 surface.DrawLine(x, y - length, x, y - gap)
266 surface.DrawLine(x, y + length, x, y + gap)
267
268 -- cover edges
269 --[[
270 local sh = scope_size - 500 / 2
271 local w = (x - sh) + 2
272 surface.DrawRect(0, 0, w, scope_size)
273 surface.DrawRect(x + sh - 2, 0, w, scope_size)
274
275 surface.SetDrawColor(255, 0, 0, 255)
276 surface.DrawLine(x, y, x + 1, y + 1)
277 ]]--
278
279 -- scope
280 surface.SetTexture(scope)
281 surface.SetDrawColor(255, 255, 255, 255)
282
283 surface.DrawTexturedRectRotated(x, y, scope_size + ScrH(), scope_size, 0)
284
285 else
286 self.DrawCrosshair = true
287 return self.BaseClass.DrawHUD(self)
288 end
289
290 end
291
292 function SWEP:AdjustMouseSensitivity()
293 return (self.Weapon:GetNWBool("Ironsights") and 0.2) or nil
294 end
295
296 -- Fix world model
297 SWEP.Pos = Vector(-1, -2, 1)
298 SWEP.Ang = Angle(0, 180, 0)
299
300 function SWEP:CreateWorldModel()
301 if not self.WModel then
302 self.WModel = ClientsideModel(self.WorldModel, RENDERGROUP_OPAQUE)
303 self.WModel:SetNoDraw(true)
304 self.WModel:SetBodygroup(1, 1)
305 end
306 return self.WModel
307 end
308
309 function SWEP:DrawWorldModel()
310 if IsValid(self.Owner) then
311 local wm = self:CreateWorldModel()
312
313 local bone = self.Owner:LookupBone("ValveBiped.Bip01_R_Hand")
314 local pos, ang = self.Owner:GetBonePosition(bone)
315
316 if bone then
317 ang:RotateAroundAxis(ang:Right(), self.Ang.p)
318 ang:RotateAroundAxis(ang:Forward(), self.Ang.y)
319 ang:RotateAroundAxis(ang:Up(), self.Ang.r)
320 wm:SetRenderOrigin(pos + ang:Right() * self.Pos.x + ang:Forward() * self.Pos.y + ang:Up() * self.Pos.z)
321 wm:SetRenderAngles(ang)
322 wm:DrawModel()
323 end
324 else
325 self:DrawModel()
326 end
327 end
328
329end
330
331function SWEP:OnRemove()
332 self:Holster()
333end
334
335if CLIENT then
336
337 SWEP.vRenderOrder = nil
338 function SWEP:ViewModelDrawn()
339
340 local vm = self.Owner:GetViewModel()
341 if !IsValid(vm) then return end
342
343 if (!self.VElements) then return end
344
345 self:UpdateBonePositions(vm)
346
347 if (!self.vRenderOrder) then
348
349 // we build a render order because sprites need to be drawn after models
350 self.vRenderOrder = {}
351
352 for k, v in pairs( self.VElements ) do
353 if (v.type == "Model") then
354 table.insert(self.vRenderOrder, 1, k)
355 elseif (v.type == "Sprite" or v.type == "Quad") then
356 table.insert(self.vRenderOrder, k)
357 end
358 end
359
360 end
361
362 for k, name in ipairs( self.vRenderOrder ) do
363
364 local v = self.VElements[name]
365 if (!v) then self.vRenderOrder = nil break end
366 if (v.hide) then continue end
367
368 local model = v.modelEnt
369 local sprite = v.spriteMaterial
370
371 if (!v.bone) then continue end
372
373 local pos, ang = self:GetBoneOrientation( self.VElements, v, vm )
374
375 if (!pos) then continue end
376
377 if (v.type == "Model" and IsValid(model)) then
378
379 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
380 ang:RotateAroundAxis(ang:Up(), v.angle.y)
381 ang:RotateAroundAxis(ang:Right(), v.angle.p)
382 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
383
384 model:SetAngles(ang)
385 //model:SetModelScale(v.size)
386 local matrix = Matrix()
387 matrix:Scale(v.size)
388 model:EnableMatrix( "RenderMultiply", matrix )
389
390 if (v.material == "") then
391 model:SetMaterial("")
392 elseif (model:GetMaterial() != v.material) then
393 model:SetMaterial( v.material )
394 end
395
396 if (v.skin and v.skin != model:GetSkin()) then
397 model:SetSkin(v.skin)
398 end
399
400 if (v.bodygroup) then
401 for k, v in pairs( v.bodygroup ) do
402 if (model:GetBodygroup(k) != v) then
403 model:SetBodygroup(k, v)
404 end
405 end
406 end
407
408 if (v.surpresslightning) then
409 render.SuppressEngineLighting(true)
410 end
411
412render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
413 render.SetBlend(v.color.a/255)
414 model:DrawModel()
415 render.SetBlend(1)
416 render.SetColorModulation(1, 1, 1)
417
418 if (v.surpresslightning) then
419 render.SuppressEngineLighting(false)
420 end
421
422 elseif (v.type == "Sprite" and sprite) then
423
424 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
425 render.SetMaterial(sprite)
426 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
427
428 elseif (v.type == "Quad" and v.draw_func) then
429
430 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
431 ang:RotateAroundAxis(ang:Up(), v.angle.y)
432 ang:RotateAroundAxis(ang:Right(), v.angle.p)
433 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
434
435 cam.Start3D2D(drawpos, ang, v.size)
436 v.draw_func( self )
437 cam.End3D2D()
438
439 end
440
441 end
442
443 end
444
445 SWEP.wRenderOrder = nil
446 function SWEP:DrawWorldModel()
447
448 if (self.ShowWorldModel == nil or self.ShowWorldModel) then
449 self:DrawModel()
450 end
451
452 if (!self.WElements) then return end
453
454 if (!self.wRenderOrder) then
455
456 self.wRenderOrder = {}
457
458 for k, v in pairs( self.WElements ) do
459 if (v.type == "Model") then
460 table.insert(self.wRenderOrder, 1, k)
461 elseif (v.type == "Sprite" or v.type == "Quad") then
462 table.insert(self.wRenderOrder, k)
463 end
464 end
465
466 end
467
468 if (IsValid(self.Owner)) then
469 bone_ent = self.Owner
470 else
471 // when the weapon is dropped
472 bone_ent = self
473 end
474
475 for k, name in pairs( self.wRenderOrder ) do
476
477 local v = self.WElements[name]
478 if (!v) then self.wRenderOrder = nil break end
479 if (v.hide) then continue end
480
481 local pos, ang
482
483 if (v.bone) then
484 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent )
485 else
486 pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" )
487 end
488
489 if (!pos) then continue end
490
491 local model = v.modelEnt
492 local sprite = v.spriteMaterial
493
494 if (v.type == "Model" and IsValid(model)) then
495
496 model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z )
497 ang:RotateAroundAxis(ang:Up(), v.angle.y)
498 ang:RotateAroundAxis(ang:Right(), v.angle.p)
499 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
500
501 model:SetAngles(ang)
502 //model:SetModelScale(v.size)
503 local matrix = Matrix()
504 matrix:Scale(v.size)
505 model:EnableMatrix( "RenderMultiply", matrix )
506
507 if (v.material == "") then
508 model:SetMaterial("")
509 elseif (model:GetMaterial() != v.material) then
510 model:SetMaterial( v.material )
511 end
512
513 if (v.skin and v.skin != model:GetSkin()) then
514 model:SetSkin(v.skin)
515 end
516
517 if (v.bodygroup) then
518 for k, v in pairs( v.bodygroup ) do
519 if (model:GetBodygroup(k) != v) then
520 model:SetBodygroup(k, v)
521 end
522 end
523 end
524
525 if (v.surpresslightning) then
526 render.SuppressEngineLighting(true)
527 end
528
529 render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255)
530 render.SetBlend(v.color.a/255)
531 model:DrawModel()
532 render.SetBlend(1)
533 render.SetColorModulation(1, 1, 1)
534
535 if (v.surpresslightning) then
536 render.SuppressEngineLighting(false)
537 end
538
539 elseif (v.type == "Sprite" and sprite) then
540
541 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
542 render.SetMaterial(sprite)
543 render.DrawSprite(drawpos, v.size.x, v.size.y, v.color)
544
545 elseif (v.type == "Quad" and v.draw_func) then
546
547 local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
548 ang:RotateAroundAxis(ang:Up(), v.angle.y)
549 ang:RotateAroundAxis(ang:Right(), v.angle.p)
550 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
551
552 cam.Start3D2D(drawpos, ang, v.size)
553 v.draw_func( self )
554 cam.End3D2D()
555
556 end
557
558 end
559
560 end
561
562 function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override )
563
564 local bone, pos, ang
565 if (tab.rel and tab.rel != "") then
566
567 local v = basetab[tab.rel]
568
569 if (!v) then return end
570
571 // Technically, if there exists an element with the same name as a bone
572 // you can get in an infinite loop. Let's just hope nobody's that stupid.
573 pos, ang = self:GetBoneOrientation( basetab, v, ent )
574
575 if (!pos) then return end
576
577 pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z
578 ang:RotateAroundAxis(ang:Up(), v.angle.y)
579 ang:RotateAroundAxis(ang:Right(), v.angle.p)
580 ang:RotateAroundAxis(ang:Forward(), v.angle.r)
581
582 else
583
584 bone = ent:LookupBone(bone_override or tab.bone)
585
586 if (!bone) then return end
587
588 pos, ang = Vector(0,0,0), Angle(0,0,0)
589 local m = ent:GetBoneMatrix(bone)
590 if (m) then
591 pos, ang = m:GetTranslation(), m:GetAngles()
592 end
593
594 if (IsValid(self.Owner) and self.Owner:IsPlayer() and
595 ent == self.Owner:GetViewModel() and self.ViewModelFlip) then
596 ang.r = -ang.r // Fixes mirrored models
597 end
598
599 end
600
601 return pos, ang
602 end
603
604 function SWEP:CreateModels( tab )
605
606 if (!tab) then return end
607
608 // Create the clientside models here because Garry says we can't do it in the render hook
609 for k, v in pairs( tab ) do
610 if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and
611 string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then
612
613 v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE)
614 if (IsValid(v.modelEnt)) then
615 v.modelEnt:SetPos(self:GetPos())
616 v.modelEnt:SetAngles(self:GetAngles())
617 v.modelEnt:SetParent(self)
618 v.modelEnt:SetNoDraw(true)
619 v.createdModel = v.model
620 else
621 v.modelEnt = nil
622 end
623
624 elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite)
625 and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then
626
627 local name = v.sprite.."-"
628 local params = { ["$basetexture"] = v.sprite }
629 // make sure we create a unique name based on the selected options
630 local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" }
631 for i, j in pairs( tocheck ) do
632 if (v[j]) then
633 params["$"..j] = 1
634 name = name.."1"
635 else
636 name = name.."0"
637 end
638 end
639
640 v.createdSprite = v.sprite
641 v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params)
642
643 end
644 end
645
646 end
647
648 local allbones
649 local hasGarryFixedBoneScalingYet = false
650
651 function SWEP:UpdateBonePositions(vm)
652
653 if self.ViewModelBoneMods then
654
655 if (!vm:GetBoneCount()) then return end
656
657 // !! WORKAROUND !! //
658 // We need to check all model names :/
659 local loopthrough = self.ViewModelBoneMods
660 if (!hasGarryFixedBoneScalingYet) then
661 allbones = {}
662 for i=0, vm:GetBoneCount() do
663 local bonename = vm:GetBoneName(i)
664 if (self.ViewModelBoneMods[bonename]) then
665 allbones[bonename] = self.ViewModelBoneMods[bonename]
666 else
667 allbones[bonename] = {
668 scale = Vector(1,1,1),
669 pos = Vector(0,0,0),
670 angle = Angle(0,0,0)
671 }
672 end
673 end
674
675 loopthrough = allbones
676 end
677 // !! ----------- !! //
678
679 for k, v in pairs( loopthrough ) do
680 local bone = vm:LookupBone(k)
681 if (!bone) then continue end
682
683 // !! WORKAROUND !! //
684 local s = Vector(v.scale.x,v.scale.y,v.scale.z)
685 local p = Vector(v.pos.x,v.pos.y,v.pos.z)
686 local ms = Vector(1,1,1)
687 if (!hasGarryFixedBoneScalingYet) then
688 local cur = vm:GetBoneParent(bone)
689 while(cur >= 0) do
690 local pscale = loopthrough[vm:GetBoneName(cur)].scale
691 ms = ms * pscale
692 cur = vm:GetBoneParent(cur)
693 end
694 end
695
696 s = s * ms
697 // !! ----------- !! //
698
699 if vm:GetManipulateBoneScale(bone) != s then
700 vm:ManipulateBoneScale( bone, s )
701 end
702 if vm:GetManipulateBoneAngles(bone) != v.angle then
703 vm:ManipulateBoneAngles( bone, v.angle )
704 end
705 if vm:GetManipulateBonePosition(bone) != p then
706 vm:ManipulateBonePosition( bone, p )
707 end
708 end
709 else
710 self:ResetBonePositions(vm)
711 end
712
713 end
714
715 function SWEP:ResetBonePositions(vm)
716
717 if (!vm:GetBoneCount()) then return end
718 for i=0, vm:GetBoneCount() do
719 vm:ManipulateBoneScale( i, Vector(1, 1, 1) )
720 vm:ManipulateBoneAngles( i, Angle(0, 0, 0) )
721 vm:ManipulateBonePosition( i, Vector(0, 0, 0) )
722 end
723
724 end
725
726 /**************************
727 Global utility code
728 **************************/
729
730 // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference).
731 // Does not copy entities of course, only copies their reference.
732 // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop
733 function table.FullCopy( tab )
734
735 if (!tab) then return nil end
736
737 local res = {}
738 for k, v in pairs( tab ) do
739 if (type(v) == "table") then
740 res[k] = table.FullCopy(v) // recursion ho!
741 elseif (type(v) == "Vector") then
742 res[k] = Vector(v.x, v.y, v.z)
743 elseif (type(v) == "Angle") then
744 res[k] = Angle(v.p, v.y, v.r)
745 else
746 res[k] = v
747 end
748 end
749
750 return res
751
752 end
753
754end